source

POST를 사용하여 Axios Excel 파일을 다운로드하면 파일이 손상됨

nicesource 2023. 7. 8. 10:59
반응형

POST를 사용하여 Axios Excel 파일을 다운로드하면 파일이 손상됨

저는 이전에 GET 엔드포인트에서 제공하는 파일을 다운로드하기 위해 Axios를 사용하고 있었습니다.엔드포인트가 변경되어 이제 POST가 되지만 매개 변수는 필요하지 않습니다.원래 다운로드 방법을 업데이트하고 있지만 손상된 파일이 반환됩니다.

downloadTemplate() {
        axios.post(DOWNLOAD_TEMPLATE_URL,
            {
                responseType: 'blob',
                headers: {
                    'Content-Disposition': "attachment; filename=template.xlsx",
                    'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                }
            })
            .then((response) => {
                const url = window.URL.createObjectURL(new Blob([response.data]));
                const link = document.createElement('a');
                link.href = url;
                link.setAttribute('download', 'template.xlsx');
                document.body.appendChild(link);
                link.click();
            })
            .catch((error) => console.log(error));
    }

그 문제가 그와 관련된 것인지 확실하지 않습니다.responseType,headers또는 응답이 처리되는 방식 또는 위의 모든 것.저는 지금까지 여러 가지 방법을 시도했지만 실패했습니다.어떤 제안이라도 해주시면 감사하겠습니다!

저는 포스트맨을 사용하여 파일을 다운로드할 수 있었기 때문에 엔드포인트에서 제공하는 파일이 괜찮은 것으로 알고 있습니다.리액트 코드에서 이 작업을 수행할 파라미터를 분류할 수 없습니다.

드디어 작동했습니다!post질문에 대한 코드 블록의 구문이 올바르지 않았고 또한 변경되었습니다.responseType"어레이 버퍼"로 이동합니다.

아래의 작업 예:

downloadTemplate() {
    axios.post(DOWNLOAD_TEMPLATE_URL, null,
        {
            headers:
            {
                'Content-Disposition': "attachment; filename=template.xlsx",
                'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            },
            responseType: 'arraybuffer',
        }
    ).then((response) => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement('a');
        link.href = url;
        link.setAttribute('download', 'template.xlsx');
        document.body.appendChild(link);
        link.click();
    })
        .catch((error) => console.log(error));
}

다음 코드를 사용하여 POST 방법에서 Excel 파일을 내보낼 수 있습니다.누군가에게 도움이 되고 시간을 절약할 수 있기를.

API용.Net Core 2.2 및 방법은 다음과 같습니다.

참고: FileStreamResult를 만들 때 응답에 대한 Content-Disposition 헤더에 파일 이름이 포함되고 스트림이 첨부 파일로 제공됩니다.

시작 시 Corsat 파일에 "내용-처분"을 추가합니다.

 app.UseCors(b => b.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials().WithExposedHeaders("Content-Disposition"));

나는 엑셀 파일 생성을 위해 EPplus 패키지를 사용하고 있습니다.

using OfficeOpenXml;
using OfficeOpenXml.Style;

    public static MemoryStream InvoiceToExcel(List<InvoiceSearchDto> invoices)
            {
                var listOfFieldNames = typeof(InvoiceSearchDto).GetProperties().Select(f => f.Name).ToList();                   
                int cellCounter = 1, recordIndex = 2;

                var ms = new MemoryStream();

                using (ExcelPackage package = new ExcelPackage(ms))
                {
                    ExcelWorksheet worksheet;

                    worksheet = package.Workbook.Worksheets.Add("New HGS");

                    // Setting the properties of the first row 
                    worksheet.Row(1).Height = 20;
                    worksheet.Row(1).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                    worksheet.Row(1).Style.Font.Bold = true;

                    // Header of the Excel sheet 
                    foreach (string header in listOfFieldNames)
                    {
                        worksheet.Cells[1, cellCounter++].Value = header;
                    }

                    // Inserting the article data into excel 
                    // sheet by using the for each loop 
                    // As we have values to the first row  
                    // we will start with second row 
                    foreach (InvoiceSearchDto invoice in invoices)
                    {
                        worksheet.Cells[recordIndex, 1].Value = invoice.CompanyName;
                        worksheet.Cells[recordIndex, 2].Value = invoice.CustomerNo;
                        worksheet.Cells[recordIndex, 3].Value = invoice.DocumentNumber;
                        worksheet.Cells[recordIndex, 4].Value = invoice.BillingPeriodStartDate.ToString("YYYY-MM-DD");
                        worksheet.Cells[recordIndex, 5].Value = invoice.BillingPeriodEndDate.ToString("YYYY-MM-DD");
                        worksheet.Cells[recordIndex, 6].Value = invoice.DateOfInvoice.ToString("YYYY-MM-DD");
                        worksheet.Cells[recordIndex, 7].Value = invoice.ExpirationDate.ToString("YYYY-MM-DD");
                        worksheet.Cells[recordIndex, 8].Value = invoice.Amount;
                        worksheet.Cells[recordIndex, 9].Value = invoice.InvoiceStatusText;

                        recordIndex++;
                    }

                    // By default, the column width is not  
                    // set to auto fit for the content 
                    // of the range, so we are using 
                    // AutoFit() method here.  
                    worksheet.Column(1).AutoFit();
                    worksheet.Column(2).AutoFit();
                    worksheet.Column(3).AutoFit();
                    worksheet.Column(4).AutoFit();
                    worksheet.Column(5).AutoFit();
                    worksheet.Column(6).AutoFit();
                    worksheet.Column(7).AutoFit();
                    worksheet.Column(8).AutoFit();
                    worksheet.Column(9).AutoFit();
                    package.Save();
                }

                ms.Position = 0;
                return ms;
            }

조치 방법 코드는 아래와 같습니다.

[HttpPost]
        [Route("[action]")]
        public IActionResult GetInvoiceWithExcel([FromBody]SearchInvoice searchInvoice)
        {
            try
            {
                if (!string.IsNullOrEmpty(searchInvoice.InvoiceDateFrom))
                {
                    searchInvoice.DateFrom = Convert.ToDateTime(searchInvoice.InvoiceDateFrom);
                }
                if (!string.IsNullOrEmpty(searchInvoice.InvoiceDateTo))
                {
                    searchInvoice.DateTo = Convert.ToDateTime(searchInvoice.InvoiceDateTo);
                }

                var invoices = invoiceBatchService.GetAllForExcel(searchInvoice.PagingParams, searchInvoice, searchInvoice.FilterObject);

                if (invoices != null)
                {
                    MemoryStream invoiceStream = ExcelConverter.InvoiceToExcel(invoices);

                    var contentType = "application/octet-stream";
                    var fileName = "Invoice.xlsx";

                    return File(invoiceStream, contentType, fileName);
                }
                else
                {
                    ResponseModel.Notification = Utility.CreateNotification("Not Found Anything", Enums.NotificationType.Warning);
                    return NotFound(ResponseModel);
                }
            }
            catch (Exception ex)
            {
                NLogger.LogError(ex, "Get Invoice With Excel");
                ResponseModel.Notification = Utility.CreateNotification(Helpers.ExceptionMessage(ex), Enums.NotificationType.Error);
                return StatusCode(500, ResponseModel);
            }
        }

마지막으로 아래와 같은 React 및 axois 코드입니다.

서비스 코드:

 return http.post(
      API_BASE_URL + "/Invoice/GetInvoiceWithExcel",
      searchInvoice,
      {
        headers: getHeaders(), // for token and others
        responseType: 'blob' // **don't forget to add this**
      }
    );
  };

그리고 조치 방법 코드는 아래와 같습니다.여기서 저는 "파일 저장기" 패키지를 사용하여 파일을 다운로드합니다.

import { saveAs } from 'file-saver';

export const getInvoiceWithExcel = invoiceInfo => {
  return dispatch => {
    dispatch({
      type: LOADING_ON
    });

    InvoiceService.getInvoiceWithExcel(invoiceInfo)
      .then(res => {

        console.log(res);

        let filename = res.headers['content-disposition']
          .split(';')
          .find((n) => n.includes('filename='))
          .replace('filename=', '')
          .trim();
        let url = window.URL
          .createObjectURL(new Blob([res.data]));
        saveAs(url, filename);


        dispatch({
          type: GET_INVOICE_EXCEL_SUCCESS,
          payload: ""
        });
        dispatch({
          type: LOADING_OFF
        });
        dispatch({
          type: ON_NOTIFY,
          payload: {
            ...res.data.notification
          }
        });
      })
      .catch(err => {
        dispatch({
          type: GET_INVOICE_EXCEL_FAILED
        });
        dispatch({
          type: LOADING_OFF
        });
        dispatch({
          type: ON_NOTIFY,
          payload: {
            ...Utility.errorResponseProcess(err.response)
          }
        });
      });
  };
};

언급URL : https://stackoverflow.com/questions/57127361/axios-excel-file-download-using-post-results-in-corrupted-file

반응형