3

In my node.js application I'm downloading multiple user files from AWS S3, compress them to single zip (with usage of Archiver npm library) file and send back to client. All the way I'm operating on streams, and yet I can't send files to client (so client would start download after successful http request).

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

Where response is express response object. zipStream is created with usage of 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;

And I know it is correct - because when I pipe it into WriteStream to some file in my file system it works correctly (I'm able to unzip written file and it has correct content). Probably I could temporarily write file in file system, send it back to client with usage of response.download and remove save file afterwards, but it looks like very inefficient solution. Any help will be greatly appreciated.

Furman
  • 2,017
  • 3
  • 25
  • 43

2 Answers2

3

So I found a source of a problem - I'll post it here just for record, in case if anyone would have same problem. Source of the problem was something totally different - I was trying to initiate a download by AJAX request, which of course won't work. I changed my frontend code and instead AJAX I used HTML anchor element with src attribute set on exactly same endpoint and it worked just fine.

Furman
  • 2,017
  • 3
  • 25
  • 43
0

I had a different problem, but rather it came from the lint. I needed to read all files from the directory, and then send them to the client in one zip. Maybe someone finds it useful.

There were 2 issues:

  • I mismatched cwd with root; see glob doc
  • Because I used PassThrough as a proxy object between Archiever and an output, lint shows stream.pipe(response) and type issue... what is a mistake - it works fine.
Witold Kupś
  • 524
  • 7
  • 14