Angular 从 node.js 发送的字节数组下载文件

Angular download file from byte array sent from node.js

我觉得我离我想做的事很近了。我在 node.js 中有以下 api get 方法,它从 SQL 服务器数据库中检索文件 varbinary(MAX)。它是在插入之前从 base64 编码的字符串转换而来的,因此从字符串中删除了内容类型信息。

node.js

router.get('/getFile', (req, res) => {
    console.log("Calling getFile for file " + req.query.serialNumber + ".")
    var serialNumber = req.query.serialNumber;
    let request = new sql.Request(conn);
    request.query('SELECT FileName + \'.\' + FileExtension AS \'File\', FileType, ContentType, SerialNumber, Chart ' +
        'FROM dbo.ChangeFiles ' +
        'WHERE SerialNumber = ' + serialNumber)
        .then(function (recordset) {
            log("Successfully retrieved file " + recordset[0].SerialNumber + " from database.");
            log("Length of blob " + recordset[0].File + " is " + recordset[0].Chart.length)
            res.status(200);
            res.setHeader('Content-Type', recordset[0].ContentType);
            res.setHeader('Content-Disposition', 'attachment;filename=' + recordset[0].File);
            res.end(Buffer.from((recordset[0].Chart)));
        }).catch(function (err) {
            log(err);
            res.status(500).send("Issue querying database!");
        });
});

这很好用,但我不清楚在 Angular 中如何检索它并提示用户下载,[=28= 也不清楚] 在线的。这是我目前的服务 class.

fileDownload.service.ts

downloadFile(serialNumber: string): Observable<any> {
    return this.http.get(this.baseURL + '/getFile', { params: { serialNumber: serialNumber } })
    .map(this.extractFile);
}


private extractFile(response: Response) {
    const file = new Blob([response.blob]);
    FileSaver.saveAs(file);
    // const url = window.URL.createObjectURL(file);
    // window.open(url);
    return file;
}

如您所见,我尝试了几种方法。 extractFile 方法的注释掉的部分根本不起作用,使用 FileSaver.saveAs 函数会产生未知类型的文件下载,因此从 node.js 发送的 headers 没有似乎影响了文件本身。

有人可以建议如何在 Angular 中继续从 node.js 成功发送的内容,以便我可以成功下载文件,无论类型如何?

提前致谢。

更新您的代码以调用 subscribe 而不是 map

我终于让它工作了。我不得不重新处理 api 调用,以便它单独发送所有文件信息,以便 MIME 类型和文件名可以分配给组件 class 中客户端的文件。出于某种原因,当我尝试在 api 中这样做时,它不起作用,所以这是我的解决方法。所以这对我有用。

node.js api

router.get('/getFile', (req, res) => {
    console.log("Calling getFile for file " + req.query.serialNumber + ".")
    var serialNumber = req.query.serialNumber;
    let request = new sql.Request(conn);
    request.query('SELECT FileName + \'.\' + FileExtension AS \'File\', FileType, ContentType, SerialNumber, Chart ' +
        'FROM dbo.ChangeFiles ' +
        'WHERE SerialNumber = ' + serialNumber)
        .then(function (recordset) {
            log("Successfully retrieved file " + recordset[0].SerialNumber + " from database.");
            log("Length of blob " + recordset[0].File + " is " + recordset[0].Chart.length)
            res.send(recordset[0]);
        }).catch(function (err) {
            log(err);
            res.status(500).send("Issue querying database!");
        });
});

组件class

  downloadFile(serialNumber: string): void {
    this.changeService.downloadFile(serialNumber).subscribe((res: any) => {
      const ab = new ArrayBuffer(res.Chart.data.length);
      const view = new Uint8Array(ab);
      for (let i = 0; i < res.Chart.data.length; i++) {
        view[i] = res.Chart.data[i];
      }
      const file = new Blob([ab], { type: res.ContentType });
      FileSaver.saveAs(file, res.File);
      console.log(res);
    });
  }

服务class

downloadFile(serialNumber: string): Observable<any> {
        return this.http.get(this.baseURL + '/getFile', { params: { serialNumber: serialNumber } })
        .map(this.extractFile);
    }

    private extractFile(response: Response) {
        // const file = new Blob([response.blob]);
        // FileSaver.saveAs(file);
        // const url = window.URL.createObjectURL(file);
        // window.open(url);
        const body = response.json();
        return body || {};
    }