Nest.js 和 Archiver - 将 zip 文件流传输到 http 响应中

Nest.js and Archiver - pipe stream zip file into http response

在我的 node.js 应用程序中,我从 AWS S3 下载多个用户文件,将它们压缩为单个 zip(使用 Archiver npm 库)文件并发送回客户端。我一直在流上操作,但我无法将文件发送到客户端(因此客户端会在成功的 http 请求后开始下载)。

const filesStreams = await this.awsService.downloadFiles(
    document?.documentFiles,
  );
const zipStream = await this.compressService.compressFiles(filesStreams);

  // ts-ignore
  response.setHeader('Content-Type', 'application/octet-stream');
  response.setHeader(
    'Content-Disposition',
    'attachment; filename="files.zip"',
  );
  zipStream.pipe(response);

其中 response 是明确的响应对象。 zipStream 是使用 Archiver 创建的:

public async compressFiles(files: DownloadedFileType[]): Promise<Archiver> {
const zip = archiver('zip');

for (const { stream, name } of files) {
  zip.append((stream as unknown) as Readable, {
    name,
  });
}

return zip;

而且我知道它是正确的 - 因为当我将它通过管道传输到 WriteStream 到我的文件系统中的某个文件时它工作正常(我能够解压缩写入的文件并且它具有正确的内容)。可能我可以暂时在文件系统中写入文件,使用 response.download 将其发送回客户端,然后删除保存文件,但它看起来是非常低效的解决方案。任何帮助将不胜感激。

所以我找到了问题的根源 - 我将 post 放在这里只是为了记录,以防有人遇到同样的问题。问题的根源完全不同——我试图通过 AJAX 请求启动下载,这当然行不通。我更改了我的前端代码,而是 AJAX 我使用了 HTML 锚元素,其 src 属性设置在完全相同的端点上并且它工作得很好。

我有一个不同的问题,但它来自 lint。我需要从目录中读取所有文件,然后将它们以一个 zip 的形式发送给客户端。也许有人觉得有用。

有 2 个问题:

  • 我将 cwdroot 不匹配;见 glob doc
  • 因为我使用 PassThrough 作为 Archiever 和输出之间的代理对象,lint 显示 stream.pipe(response) 并输入问题...这是个错误 - 它工作正常。