You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React浏览器下载经C# Aspose Cells处理的Excel文件损坏求助

React下载Excel文件损坏问题解决

问题场景

通过React调用C# API处理Excel文件:API接收文件后用Aspose Cells修改,将修改后的文件转为Byte[]返回前端;前端将Byte[]转为Blob触发下载,但打开文件时提示损坏。

原代码

服务端C# API代码

public async Task<Byte[]> ExportToExcel(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return null;
    }
    try
    {
        using (var stream = file.OpenReadStream())
        {
            Workbook workbook = new Workbook(stream);
            var worksheet = workbook.Worksheets[0];
            Cells cells = worksheet.Cells;

            FindOptions findOptions = new FindOptions();
            findOptions.CaseSensitive = false;
            findOptions.LookInType = LookInType.Values;
            findOptions.LookAtType = LookAtType.Contains;

            // Doing modifications in Excel file....

            // Save the modified workbook as Excel file
            var excelMemoryStream = new MemoryStream();
            workbook.Save(excelMemoryStream, SaveFormat.Xlsx);
            byte[] data = excelMemoryStream.ToArray();

            return data;
        }
    }
    catch (Exception ex)
    {
        throw;
    }
}

客户端React代码

const onBtExport = () => {
const csvData = gridRef.current.api.getDataAsExcel();
console.log(csvData);
instance
  .acquireTokenSilent({
    ...accessToken,
    account: accounts[0],
  })
  .then(async (response) => {
    const formData = new FormData();
    formData.append('file', csvData);
    ExportToExcel(response.accessToken, formData).then((res) => {
      if (res.data.Status === true) {
        console.log(res.data.Data);
        const blob = new Blob([res.data.Data],{ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
        console.log(blob);
        const a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = 'ContractSummaryReport.xlsx';
        a.click();

        URL.revokeObjectURL(a.href);
        
      } else {
        toast.error(res.data.Message);
        
      }
    });
  });
};

问题根源

  1. 服务端:返回Byte[]时,ASP.NET会自动将其序列化为JSON数组(如[255,216,255,...]),而非原始二进制流,前端拿到的是数字数组而非有效文件数据。
  2. 客户端:未设置正确的responseType,Axios默认将响应解析为JSON,导致二进制数据被错误转换;同时直接将JSON化的数字数组转为Blob,无法还原有效Excel文件。

修正方案

服务端代码修改

将返回类型改为FileStreamResult,直接输出二进制流并指定正确MIME类型:

public async Task<IActionResult> ExportToExcel(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return BadRequest("上传文件为空");
    }
    try
    {
        using (var stream = file.OpenReadStream())
        {
            Workbook workbook = new Workbook(stream);
            var worksheet = workbook.Worksheets[0];
            Cells cells = worksheet.Cells;

            FindOptions findOptions = new FindOptions();
            findOptions.CaseSensitive = false;
            findOptions.LookInType = LookInType.Values;
            findOptions.LookAtType = LookAtType.Contains;

            // 执行Excel修改操作...

            var excelMemoryStream = new MemoryStream();
            workbook.Save(excelMemoryStream, SaveFormat.Xlsx);
            excelMemoryStream.Position = 0; // 重置流指针到起始位置

            // 返回二进制文件流
            return File(
                excelMemoryStream, 
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 
                "ContractSummaryReport.xlsx"
            );
        }
    }
    catch (Exception ex)
    {
        return StatusCode(500, "文件处理失败:" + ex.Message);
    }
}

客户端代码修改

  1. 设置Axios请求的responseType: 'arraybuffer',确保接收原始二进制数据。
  2. 简化响应处理,直接用返回的二进制数据创建Blob。
const onBtExport = () => {
  const excelBlob = gridRef.current.api.getDataAsExcel();
  instance
    .acquireTokenSilent({
      ...accessToken,
      account: accounts[0],
    })
    .then(async (response) => {
      const formData = new FormData();
      formData.append('file', excelBlob);

      // 调用API时指定responseType
      ExportToExcel(response.accessToken, formData)
        .then((res) => {
          const blob = new Blob([res.data], { 
            type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 
          });
          const a = document.createElement('a');
          a.href = URL.createObjectURL(blob);
          a.download = 'ContractSummaryReport.xlsx';
          a.click();
          URL.revokeObjectURL(a.href);
        })
        .catch(() => {
          toast.error('文件下载失败,请重试');
        });
    });
};

// 封装的ExportToExcel请求,添加responseType配置
const ExportToExcel = (token, formData) => {
  return axios.post('/api/ExportToExcel', formData, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'multipart/form-data'
    },
    responseType: 'arraybuffer' // 关键配置,确保接收二进制数据
  });
};

关键说明

  • 服务端返回FileStreamResult能避免JSON序列化导致的二进制数据失真,同时自动设置正确的响应头。
  • 客户端必须设置responseType: 'arraybuffer',否则Axios会将二进制数据解析为UTF-8字符串,导致Blob损坏。
  • ag-Grid的getDataAsExcel()返回的是Blob对象,直接添加到FormData即可,无需额外转换。

内容的提问来源于stack exchange,提问作者Suprateem Bose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 12:17:37