首页 新闻 会员 周边 捐助

C# 读取物理文件并下载

0
悬赏园豆:60 [已解决问题] 解决于 2025-09-10 16:33

C# net8 实现下载文件至本地
API代码

[HttpPost]
[Route("DownloadFile")]
[ApiDescriptionSettings(Tag = "下载文件")]
public async Task<IActionResult> DownloadFile(string id, bool isGroup)
{
try
{
await _fileService.DownloadFile(id, isGroup);
// 获取文件路径列表
List<FileUploadAttachment> filePaths = await _fileService.GetFilePathAsync(id, isGroup);

    // 检查传入的文件路径列表是否为空
    if (filePaths == null || filePaths.Count == 0)
    {
        return new BadRequestObjectResult("文件路径列表不能为空");
    }

    // 单个文件下载处理
    if (filePaths.Count == 1)
    {
        string filePath = filePaths[0].Path;

        // 检查文件是否存在
        if (!System.IO.File.Exists(filePath))
        {
            return new NotFoundObjectResult($"文件不存在: {filePath}");
        }

        // 读取文件内容
        byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
        string extName = StaticData.GetFileExt(filePaths[0].ExtName);//文件后缀转换
        // 返回文件下载响应
        return new FileContentResult(fileBytes, extName)
        {
            FileDownloadName = filePaths[0].FileName
        };
    }

    // 多个文件下载处理 - 创建ZIP压缩包
    using (var memoryStream = new MemoryStream())
    {
        using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
        {
            foreach (FileUploadAttachment fi in filePaths)
            {
                string filePath = fi.Path;
                // 跳过不存在的文件
                if (!System.IO.File.Exists(filePath))
                {
                    continue;
                }

                try
                {
                    // 在ZIP文件中创建条目
                    string entryName = Path.GetFileName(filePath);
                    ZipArchiveEntry entry = zipArchive.CreateEntry(entryName);

                    // 将文件内容写入ZIP条目
                    using (Stream entryStream = entry.Open())
                    using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    {
                        await fileStream.CopyToAsync(entryStream);
                    }
                }
                catch (Exception ex)
                {
                    // 记录错误但继续处理其他文件
                    Console.WriteLine($"处理文件 {filePath} 时出错: {ex.Message}");
                }
            }

            // 检查ZIP中是否有文件
            if (zipArchive.Entries.Count == 0)
            {
                return new NotFoundObjectResult("所有请求的文件都不存在");
            }
        }

        // 准备ZIP文件下载
        memoryStream.Position = 0;
        string zipFileName = $"{id}_{DateTime.Now:yyyyMMddHHmmss}.zip";

        // 返回ZIP文件下载响应
        return new FileContentResult(memoryStream.ToArray(), "application/zip")
        {
            FileDownloadName = zipFileName
        };
    }
}
catch (Exception ex)
{
    // 返回服务器内部错误信息
    return new ObjectResult($"服务器内部错误: {ex.Message}")
    {
        StatusCode = (int)HttpStatusCode.InternalServerError
    };
}

}

前端实现 VUE3 + ElementPlus
const downloadFile = (file) => {
const formData = new FormData();
formData.append("id", "D8AF64DE0F514A1FB093746D1F5AEBA5");
formData.append("isGroup", false);
hfApi
.DownloadFile(formData)
.then((res) => {
console.log(res);
console.log('Blob验证111:', new Blob([res.request.response], {
type: res.headers["content-type"] || "application/octet-stream",
}));
console.log('Blob验证:', res.request.response instanceof Blob); // 应该输出true

  for (const key in res) {
    console.log(`Blob验证${key}:`, res[key] instanceof Blob); 
  }

  //console.log(res.headers);
  //console.log(res.data);
  // 修改点1:获取二进制数据

  let fileName = file.name;
  const contentDisposition = res.headers["content-disposition"];
  if (contentDisposition) {
    // 改进后的正则表达式,处理带编码文件名和不同格式
    const fileNameMatch = contentDisposition.match(
      /filename\*?=([^']+)'\w*'([^;]+)|filename="?([^";]+)"?/i
    );
    if (fileNameMatch) {
      // 优先使用UTF-8编码的文件名(filename*=格式)
      fileName = fileNameMatch[2]
        ? decodeURIComponent(fileNameMatch[2])
        : fileNameMatch[3] || file.name;
    }
  }

  // 直接从响应数据创建Blob
  const blob = new Blob([res.request.response], {
    type: res.headers["content-type"] || "application/octet-stream",
  });
  // 创建下载链接
  const url = window.URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = fileName;
  link.style.display = "none";
  document.body.appendChild(link);
  link.click();
  // 清理
  setTimeout(() => {
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url);
  }, 100);
})
.catch((error) => {
  ElMessage.error(`文件下载失败:${error}`);
});

};

问题:
能下载文件,但是下载的文件大小不一致并且打开不了文件
接口返回的是一个图片,能直接预览,我物理文件实际是35kb,下载后变成了50kb

这是接口请求配置

接口响应以及控制台打印,请求响应就36.7kb

下载后就变成五十多kb了
index.vue
{
"data": "�PNG\r\n*****0IEND�B�", "status": 200, "statusText": "OK", "headers": { "content-disposition": "attachment; filename=2025-03-12_10-31-55.png; filename*=UTF-8''2025-03-12_10-31-55.png", "content-length": "36302", "content-type": "image/png" }, "config": { "transitional": { "silentJSONParsing": true, "forcedJSONParsing": true, "clarifyTimeoutError": false }, "transformRequest": [ null ], "transformResponse": [ null ], "timeout": 5000, "xsrfCookieName": "XSRF-TOKEN", "xsrfHeaderName": "X-XSRF-TOKEN", "maxContentLength": -1, "maxBodyLength": -1, "env": { "FormData": null }, "headers": { "Accept": "application/json, text/plain, */*", "Authorization": "Bearer eyJhbGciOiJIUzI1iLCJhdWQiOiJwb3dlcmJ5IEZ1cmlvbiJ9.ZEIS8b9XQiI_RZI60eCclynw04pMggMYcmnupZg7EyU", "apisign": "T!B$FMU=#_F(-_VBF((GN=F*P*YFZ@=LFAV-KFKOOT=F+MXQSHE()XPF%VQ-F^PY*HECQ^&==" }, "method": "post", "url": "http://localhost:6538/api/file/DownloadFile", "responseType": "blob", "data": {} }, "request": { "custom": { "events": {}, "requestHeaders": {}, "responseHeaders": {}, "method": "POST", "url": "http://localhost:6538/api/file/DownloadFile", "async": true, "options": { "url": "http://localhost:6538/api/file/DownloadFile", "type": "POST", "body": {} }, "timeout": 20, "xhr": {} }, "readyState": 4, "responseURL": "http://localhost:6538/api/file/DownloadFile", "status": 200, "statusText": "OK", "responseType": "", "response": "�PNG\r\n\*****0IEND�B�",
"responseXML": null,
"timeout": 5000
}
}
这是我请求返回的参数

求大佬解惑,为什么就下载的不正确

HoFei1113的主页 HoFei1113 | 初学一级 | 园豆:148
提问于:2025-09-08 17:58
< >
分享
最佳答案
0

先确定问题,然后才能解决问题。

1、api:

单独测试api,按照你描述的图片能预览到,那说明api没问题。

2、vue:

检查前端vue的调用问题。请求时候responseType:'blob'参数就ok了。

看你截图是responseType不对的问题。service封装问题?直接用axios是ok的。

 

 无responseType: "blob",

 

responseType: "blob",
收获园豆:60
张朋举 | 老鸟四级 |园豆:2051 | 2025-09-10 10:27


api也是有blob的

HoFei1113 | 园豆:148 (初学一级) | 2025-09-10 16:28

已经用了其他方式解决,不通过blob了,最终的问题是编码问题,二进制被多次转码,怎么转都会有误差

HoFei1113 | 园豆:148 (初学一级) | 2025-09-10 16:29
其他回答(1)
0

解决方案就是直接传编码,前端通过编码转换为文件

HoFei1113 | 园豆:148 (初学一级) | 2025-09-10 16:30
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册