节点+角度:使用HTTP请求下载文件

时间:2019-05-20 10:49:36

标签: node.js angular download http-headers

我尝试了400种语法和标头组合,但我不知道如何从Angular进行HTTP调用以从NodeJS服务器检索文件。

在Stackoverflow上找到并尝试,但无济于事:

Download file from http post request - Angular 6

How download a file from HttpClient

Download a file from NodeJS Server using Express

How do I download a file with Angular2

它不能是简单的<a download>标记,也不能是公共express.static()文件夹,因为对文件的访问受到限制,并且我需要传递一个JWT令牌(在Node中,我有一个Express身份验证中间件,如果标头中未提供令牌或令牌无效,它将拒绝该请求。

该文件是GZIP:./dumps/dump.gz,重812 Kb。

我确实设法下载了文件,但是无论如何,它的重量为1.4 MB或94字节(大小错误),并且无法打开(7zip can't open file downloads/dump.gz as archive)。

我尝试过的角度(多次尝试):

import { saveAs } from 'file-saver';

let headers = new Headers({
    "Authorization": "Bearer " + user.jwt, // I need this in the headers

    "Content-Type" : "application/octet-stream", // Tried with and without, "application/gzip", "application/json", no difference

    "responseType": "blob" as "json", // Tried with and without, "text", "json", no difference

    "Access-Control-Expose-Headers" : "Content-Disposition" // Tried with and without, no difference
})

this.http
    .get("/download/dump", { headers })
    .toPromise()
    .then(res => {

        const blob = new Blob([res["_body"]] , { type: "application/octet-stream;"} );  // Error : body is not a blob or an array buffer
        // const blob = new Blob([res["_body"]]); // Same result
        // const blob = new Blob([res.blob()]); // Error : body is not a blob or an array buffer

        saveAs(blob, "dump.gz"); // Saves a big corrupted file

        // window.URL.createObjectURL(new Blob(blob, {type: 'blob'})); Saves a 94 byte corrupted file. Tried {type: 'gzip'}, same thing
    })
    .catch(err => console.error("download error = ", err))

我尝试过的操作节点端(多次尝试):

编辑

Node是无辜的,因为我可以在禁用身份验证后直接从Chrome检索文件。因此,后端工作正常,问题出在Angular中。

app.get( "/download/dump", authenticate, (req:Request, res:Response) => {
    const file = path.resolve(__dirname, `./dumps/dump.gz`);

    res
        .set({ // Tried with and without headers, doesn't seem to do anything
            "Content-Disposition" : "attachment",  // Tried with and without
            "filename" : "dump.gz", // Tried with and without
            "filename*" : "dump.gz",  // Tried with and without
            "Content-Encoding" : "gzip",  // Tried with and without
            "Content-Type" : "application/gzip"  // Tried with and without, "application/text", "application/json", no difference 
        })
        .sendFile(file); // getting a big corrupted file
        // .download(file); // Same result (big corrupted file)
})

1 个答案:

答案 0 :(得分:0)

假设您使用的是新的HttpClient(来自角度)(自角度4起可用),

前面

import { saveAs } from 'file-saver';
import {HttpHeaders} from "@angular/common/http";

let headers = new HttpHeaders({
    "Authorization": "Bearer " + user.jwt, // Auth header
    //No other headers needed
});

this.http
    .get("/download/dump", { headers, responseType: "blob" }) //set response Type properly (it is not part of headers)
    .toPromise()
    .then(blob => {
        saveAs(blob, "dump.gz"); 
    })
    .catch(err => console.error("download error = ", err))

后端

app.get( "/download/dump", authenticate, (req:Request, res:Response) => {
    const file = path.resolve(__dirname, `./dumps/dump.gz`);
    //No need for special headers
    res.download(file); 
})