JavaScript文件下载 / Blob创建

发布于 2025-02-05 07:22:31 字数 2735 浏览 2 评论 0 原文

我有一个vue.js前端和dotnet核心API。我正在尝试从API下载文件(文件的来源无关紧要,但是我正在构造响应,如下所示:

[HttpGet]
[Route("[action]/{attachmentId:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DownloadAttachment(int attachmentId)
{
    try
    {
        var file = await _attachmentService.DownloadAttachment(attachmentId);
        return File(file.FileContent, file.FileType, file.FileName);
    }
    catch (Exception e)
    {
        _logger.logError(e, "DownloadAttachment: attachmentId:{@attachmentId}", attachmentId);
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}

访问Postman中的此端点给我预期的响应:

这是常规的PDF。注意文件内容长度约为290kb。

尝试将此文件下载到vue.js frontend(使用Axios),我尝试了以下2种方法:

1。

首先,我尝试使用npm库,称为 js-file-download 带有以下代码:

import fileDownload from "js-file-download";

const downloadAttachment = async (attachmentId, filename) => {
  try {
    var result = await api.get(`/api/Attachments/DownloadAttachment/${attachmentId}`);
    fileDownload(result.data, filename, result.headers.type);
  } catch (error) {
    console.error(error);
    return error;
  }
}

此代码给我一个损坏的pdf文件,其中有2个空白页面(原始pdf具有2个,内容的页面)似乎大约是应有的大小的两倍:

“在此处输入图像说明”

2。

我还尝试了使用以下代码创建JavaScript Blob(不包括上述库):

const downloadAttachment = async (attachmentId, filename) => {
  try {
    var result = await api.get(`/api/Attachments/DownloadAttachment/${attachmentId}`);
    let blob = new File([result.data], filename, { type: result.headers["content-type"] });
    let exportUrl = URL.createObjectURL(blob);
    window.location.assign(exportUrl);
    URL.revokeObjectURL(exportUrl);
  } catch (error) {
    console.error(error);
    return error;
  }
}

//i.sstatic.net/unqsx.png 这使我完全是损坏的510kb文件。即使是记录斑点的控制台的大小为522881,而API标头的响应的内容长度为297167:

我无法弄清楚发生了什么或额外数据的来源。其他文件类型(例如Excel文件或图像)也会发生同样的情况,尽管有趣的是下载非常简单的文件类型,例如TXT或CSV文件并不会引起此问题。

I've a Vue.JS frontend and a dotnet core API. I'm trying to download a file from the API (the source of the file is irrelevant, but I'm constructing the response as follows:

[HttpGet]
[Route("[action]/{attachmentId:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DownloadAttachment(int attachmentId)
{
    try
    {
        var file = await _attachmentService.DownloadAttachment(attachmentId);
        return File(file.FileContent, file.FileType, file.FileName);
    }
    catch (Exception e)
    {
        _logger.logError(e, "DownloadAttachment: attachmentId:{@attachmentId}", attachmentId);
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}

Accessing this endpoint in postman give's me the expected response:

enter image description here
enter image description here

It's a regular PDF. Note the file content length is around 290KB.

Attempting to download this file to Vue.JS frontend (using axios), I've tried the following 2 methods:

1.

First, I tried making use of npm library called js-file-download with the following code:

import fileDownload from "js-file-download";

const downloadAttachment = async (attachmentId, filename) => {
  try {
    var result = await api.get(`/api/Attachments/DownloadAttachment/${attachmentId}`);
    fileDownload(result.data, filename, result.headers.type);
  } catch (error) {
    console.error(error);
    return error;
  }
}

This code give's me a broken PDF file, which has 2 blank pages (the original PDF has 2 pages of content) which appears to be roughly double the size it's supposed to be:

enter image description here

2.

I also tried by creating a JavaScript blob (excluding the above mentioned library) with the following code:

const downloadAttachment = async (attachmentId, filename) => {
  try {
    var result = await api.get(`/api/Attachments/DownloadAttachment/${attachmentId}`);
    let blob = new File([result.data], filename, { type: result.headers["content-type"] });
    let exportUrl = URL.createObjectURL(blob);
    window.location.assign(exportUrl);
    URL.revokeObjectURL(exportUrl);
  } catch (error) {
    console.error(error);
    return error;
  }
}

File wise, this give's me exactly the same broken 510kb file. Even console logging the blob shows a size of 522881 while the response from the api's headers shows a content length of 297167:

enter image description here

I cannot figure out what is going on or where the extra data is coming from. The same happens to other file types such as excel files or images, though interestingly downloading very simple file types such as txt or csv files does not cause this issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

殤城〤 2025-02-12 07:22:31

在发布自己的问题之前,请仔细研究“类似的问题”,我发现了一些导致答案的暗示。原来,我需要调整我使用Axios进行的API调用,以包括适当的响应类型。更改以下问题解决了我的问题:

var result = await api.post(`/api/Attachments/DownloadAttachment/${attachmentId}`);

更改为:

var result = await api.post(`/api/Attachments/DownloadAttachment/${attachmentId}`, {
    headers: {
      "Content-Disposition": "attachment"
    },
    responseType: "blob"
  }
);

Looking through the "Similar Questions" before posting my own question I found a hint of something that led to an answer. Turns out I needed to adjust me API call that I make with axios to include the appropriate response type. Changing the following fixed my issue:

var result = await api.post(`/api/Attachments/DownloadAttachment/${attachmentId}`);

changes to:

var result = await api.post(`/api/Attachments/DownloadAttachment/${attachmentId}`, {
    headers: {
      "Content-Disposition": "attachment"
    },
    responseType: "blob"
  }
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文