2

我正在尝试使用在 Node JS 和 Express 中创建的包装 API 访问 AWS S3 签名 URL。

我正在重定向一个 url 以使用 nginx 调用 Node API。在 Node API 中,我在从 Node API 返回响应之前根据 S3 URL 返回的文件类型设置“Content-Type”响应标头。

当我通过包装节点 API 访问 URL 以在 S3 中获取文档时,我没有得到任何内容。如果是 PDF 文件,我会收到空​​白屏幕。

下面是我用来在 Node wrapper API 中从 S3 获取文档并中继相同响应的代码块。

const request = require('request');

request(s3SignedURL, function (error, result, body) {
    if (!error) {
        res.header('Content-Type','application/pdf');
        res.end(body);
    } else {
        res.status(500).send(error);
    }
});

[编辑]

我将上传的 S3 文件的详细信息存储在一个表中,并在有人尝试访问它时使用该表来获取文档。下面是使用的完整代码。

const S3 = new AWS.S3();

app.get("/getFile/*", function (req, res) {
    var urlInfo = req.url;
    var urlInfoList = urlInfo.split("/");
    var accessCode = urlInfoList[2];
    var accessID = urlInfoList[3];

    if (!!accessID && !!accessCode) {
        db.getFileInfo(accessCode, accessID).then(function (fileInfo) {
            if (fileInfo.length > 0) {
                var S3Options = {
                    Bucket: Bucketname,
                    Key: fileInfo[0].fileS3Key,
                };
                S3.getObject(S3Options, function (err, data) {
                    res.attachment(fileInfo[0].fileS3Key);
                    res.send(data.Body);
                });

                // request(fileInfo[0].fileS3URL).pipe(res.set('Content-Type', 'application/pdf').set('Content-Disposition', 'inline'));
            } else {
                res.status(404).send("<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr></body></html>");
            }
        }, function (fileErr) {
            console.log('fileErr');
            console.log(fileErr);
            res.status(404).send("<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr></body></html>");
        });
    } else {
        res.status(404).send("<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr></body></html>");
    }
});

在这方面的任何帮助都将非常有用。

4

1 回答 1

2

您得到一个空白屏幕,因为您还需要发送Content-Disposition参数。

顺便说一句,预签名 url 的目的是从公开暴露的环境(AWS 环境之外)临时访问 s3 对象。您不必使用来自后端服务的预签名 URL 机制,您可以通过 SDK 安全地访问对象

const express = require('express');
const app = express();
const request = require('request');

app.get('/download-file', function (req, res) {

  // sdk way
  var s3 = new AWS.S3({});
  var options = {
    Bucket: 'my-bucket-name',
    Key: file,
  };
  s3.getObject(options, function (err, data) {
    res.setHeader('Content-disposition', `inline; filename="${filename}"`);
    res.end(data.Body, 'binary');
  });

  // http way
  request('https://s3-ap-southeast-2.amazonaws.com/my-bucket-name/mypdf.pdf')
    .pipe(res.set('Content-Type', 'application/pdf').set('Content-Disposition', 'inline; filename="mypdf.pdf"'))
})
于 2019-12-20T14:07:41.540 回答