简体   繁体   中英

Javascript file download / blob creation

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:

在此处输入图像描述 在此处输入图像描述

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:

在此处输入图像描述

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:

在此处输入图像描述

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.

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"
  }
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM