3

I'm facing some timeout problems with a "middleware" (from now on file-service) service developed with NestJS and AWS-S3.

The file-service has two main purposes:

  • Act as an object storage abstraction layer, to allow the backend to upload files to different storage services completely transparent to the user.
  • Receive signed tokens as a url query parameter with file/object information, verify access to resource and stream it.

Upload works without problem.

Download small files has no problems too.

But when I try to download large files (> 50MB), after a few seconds, the connection beaks down because of a timeout and as you can figure out the download fails.

I've been spending some days looking for a solutions and reading docs.

Here some of them:

But nothing works.

Here the code:

Storage definition class

export class S3Storage implements StorageInterface {
 config: any;

 private s3;

 constructor() {}

 async initialize(config: S3ConfigInterface): Promise<void> {
   this.config = config;
   this.s3 = new AWS.S3();

   // initialize S3 Configuration
   AWS.config.update({
     accessKeyId: config.accessKeyId,
     secretAccessKey: config.secretAccessKey,
     region: config.region
   });
 }

 async downloadFile(target: FileDto): Promise<Readable> {
   const params = {
     Bucket: this.config.Bucket,
     Key: target.sourcePath
   };

   return this.s3.getObject(params).createReadStream();
 }
}

Download method

private async downloadOne(target: FileDto, request, response) {
  const storage = await this.provider.getStorage(target.datasource);

  response.setHeader('Content-Type', mime.lookup(target.filename) ||    'application/octet-stream');
  response.setHeader('Content-Disposition',  `filename="${path.basename(target.filename)}";`);
  const stream = await storage.downloadFile(target);
  stream.pipe(response);

  // await download and exit
  await new Promise((resolve, reject) => {
    stream.on('end', () => {
      resolve(`${target.filename} has been downloaded`);
    });
    stream.on('error', () => {
      reject(`${target.filename} could not be downloaded`);
    });
  });
}

If any one has faced the same issue (or similar) or any one has any idea (useful or not), I will appreciate any help or advice.

Thank you in advance.

marc
  • 527
  • 6
  • 23
  • 1
    Hi, I'm facing the same problem... Do you have any updates, or how did you solve it? But the issue only appears when I use Amazon Aurora DB instance instead of usual RDS. – Armine Jan 19 '22 at 11:19
  • Does this answer your question? [streaming files from AWS S3 with NodeJS](https://stackoverflow.com/questions/70625366/streaming-files-from-aws-s3-with-nodejs) – about14sheep Aug 07 '22 at 02:08

1 Answers1

0

I had the same issue, and here is how I solved it on my side: instead of processing the file by directly getting the stream from S3, I decided to download the content to a temp file (Amazon backend server for my API) and process already the stream from that temp file. Afterwards, I removed the temp file in order not to fill the hard drive.

Armine
  • 1,675
  • 2
  • 24
  • 40