ReactJS:从 S3 渲染私有图像资产

Jam*_*mes 6 amazon-s3 amazon-web-services node.js reactjs react-native

我正在使用 NodeJS 后端 API 服务器,它允许前端(ReactJS / React Native)使用表单数据上传图像。这是我正在使用的代码:

const s3 = new aws.S3({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: "us-east-1",
});

...

const upload = multer({
  storage: multerS3({
    s3,
    bucket: process.env.AWS_BUCKET,
    acl: 'private',
    metadata(req, file, cb) {
      cb(null, {fieldName: file.fieldname});
    },
    key(req, file, cb) {
      cb(null, Date.now().toString() + '.png');
    }
  })
})

...

app.post('/upload', upload.single('photo'), (req, res, next) => {
  res.json(req.file)
})
Run Code Online (Sandbox Code Playgroud)

API 服务器正常工作,图像使用AWS_ACCESS_KEY_ID和上传到私有安全存储桶中AWS_SECRET_ACCESS_KEY

但是现在我希望能够在 ReactJS 或 React Native 上渲染此图像。您是否建议构建另一个名为 like 的 NodeJS 路由/render并以某种方式将其流式传输到后端?如果是,我该怎么做?

或者,我是否应该直接从前端渲染它并冒着将AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY键暴露给用户的风险?

Jam*_*mes 12

经过多次尝试和错误,我发现最优雅的解决方案是让 NodeJS 来处理与 S3 的通信。然后前端将GET通过路由从 NodeJS 获取图像,可以按如下方式完成:

  app.get("/image/:imageId", function(req, res, next) {
    var params = { Bucket: keys.AWS_BUCKET, Key: req.params.imageId };
    s3.getObject(params, function(err, data) {
      if (err) {
        return res.send({ error: err });
      }
      res.send(data.Body);
    });
  });
Run Code Online (Sandbox Code Playgroud)

为什么我认为这比luboskmac提出的解决方案更优雅?

首先,我不会在任何时候向公众公开资产。我只是GET向最终用户透露 NodeJS路由。

其次,如果我想限制对这条路线的访问,我可以简单地passportJS在 NodeJS 内部使用,例如,将资产的访问权限限制为仅登录用户。这在许多情况下都很有用,例如在 GDPR 要求的情况下。