Загрузка файла NodeJS из корзины AWS S3

#javascript #node.js #amazon-web-services #express #amazon-s3

#javascript #node.js #amazon-веб-сервисы #экспресс #amazon-s3

Вопрос:

Я пытаюсь создать конечную точку в NodeJS / Express для загрузки содержимого из моей корзины AWS S3.

Это работает хорошо, я могу загрузить файл на стороне клиента, но я также вижу предварительный просмотр потока на вкладке Сеть, что раздражает…

ВОПРОС

Мне интересно, правильно ли то, что я делаю, и является ли это хорошей практикой. Также хотелось бы знать, нормально ли видеть выходной поток на вкладке Сеть.

Как мне правильно отправить файл из S3 в мое клиентское приложение с помощью NodeJS / Express?

Я почти уверен, что запросы других веб-сайтов не позволяют просматривать содержимое с помощью: «Не удается загрузить данные ответа«.


Это то, что я делаю в своем приложении NodeJS, чтобы получить файл потока из AWS S3:

 download(fileId) {
  const fileObjectStream = app.s3
    .getObject({
      Key: fileId
    })
    .createReadStream();
  this.res.set("Content-Type", "application/octet-stream");
  this.res.set(
    "Content-Disposition",
    'attachment; filename="'   fileId   '"'
  );
  fileObjectStream.pipe(this.res);
} 

И на стороне клиента я вижу это:

введите описание изображения здесь

Комментарии:

1. Я предполагаю, что другой вариант — заставить nodejs создать подписанный URL-адрес и вместо этого отправить его клиенту. Затем клиент может использовать этот подписанный URL-адрес для доступа к содержимому S3

Ответ №1:

Я думаю, что проблема связана с заголовком :

           //this line will set proper header for file and make it downloadable in client's browser

          res.attachment(key); 

          // this will execute download 
          s3.getObject(bucketParams)
          .createReadStream()
          .pipe(res);
 

Итак, код должен быть таким (это то, что я делаю в своем файле обработки проекта как res.attachment или res.json в случае ошибки, чтобы клиент мог отобразить ошибку конечному пользователю) :

 router.route("/downloadFile").get((req, res) => {
      const query = req.query; //param from client
      const key = query.key;//param from client
      const bucketName = query.bucket//param from client

      var bucketParams = {
        Bucket: bucketName,  
        Key: key
      };

      //I assume you are using AWS SDK
      s3 = new AWS.S3({ apiVersion: "2006-03-01" });

      s3.getObject(bucketParams, function(err, data) {
        if (err) {
          // cannot get file, err = AWS error response, 
          // return json to client
          return res.json({
            success: false,
            error: err
          });
        } else {
          res.attachment(key); //sets correct header (fixes your issue ) 
          //if all is fine, bucket and file exist, it will return file to client
          s3.getObject(bucketParams)
            .createReadStream()
            .pipe(res);
        }
      });
    });
 

Комментарии:

1. Как это запускает загрузку на стороне клиента?

2. Ну, на стороне клиента правильный заголовок — это то, что запускает файл. В обычном HTTP-ответе заголовок ответа на размещение содержимого представляет собой заголовок, указывающий, ожидается ли, что содержимое будет отображаться встроенным в браузере, то есть как веб-страница или как часть веб-страницы, или как вложение, которое загружается и сохраняется локально. Например, расположение содержимого: вложение; filename =»whateverIfFileName.jpg » отправит браузеру указание на загрузку файла…. В моем коде выше res.attachment (ключ) — это то, что устанавливает правильный заголовок файла, чтобы файл можно было загрузить браузером. Я надеюсь, что это поможет.