像这篇来自heroku的文章展示了可以在Node服务器上签署请求,并从客户端直接将大文件上传到S3,但是我还没有找到一个类似的解决方案来直接从S3下载大文件到客户端。
关于我正在尝试做的更多信息:
我正在用Heroku托管的Node js服务器构建一个React web应用程序。用户创建和编辑音频文件,然后存储在S3桶中。
在接下来的会话中,音频必须再次从S3桶加载到用户的浏览器中。要做到这一点,web应用程序向node js服务器发送一个请求,然后服务器检索文件并将其发送给客户端,端点如下:
// LOAD AUDIO
router.get("/getaudio/:userEmail/:projectId/:sectionId", async (req, res) => {
//create key from user/project/section IDs
const userEmail = req.params.userEmail;
const projectId = req.params.projectId;
const sectionId = req.params.sectionId;
const key = `${userEmail}/${projectId}/${sectionId}.webm`;
const params = {
Key: key,
Bucket: s3BucketName
}
s3.getObject(params, function (error, data) {
if (error) {
console.error(error);
}
res.send(data);
});
});
这里的问题是音频文件可能非常大(长达1.5小时)。将这些文件加载到Node js服务器并,然后将它们发送到客户端,感觉非常低效,并且可能导致我的Heroku dyno上不必要的负载,以及用户的长时间等待时间。
然而,我不想在我的客户端直接使用AWS SDK(完全切断服务器),因为我被告知这是不好的做法,可能会暴露您的环境变量。
是否有一种方法可以安全地从s3桶直接下载大文件到React客户端?
你可以生成一个presigned URL node . js服务器授予访问s3对象,该URL发送给你反应程序和下载的文件直接从应用程序反应。
需要注意的是,预设的URL默认在15分钟内过期。因此,如果您需要增加过期时间,您可以通过传递Expires
参数来指定URL的有效期(以秒为单位)。
你的node.js处理程序可能看起来像这样:
router.get("/getaudio/:userEmail/:projectId/:sectionId", async (req, res, next) => {
//create key from user/project/section IDs
const userEmail = req.params.userEmail;
const projectId = req.params.projectId;
const sectionId = req.params.sectionId;
const key = `${userEmail}/${projectId}/${sectionId}.webm`;
const params = {
Key: key,
Bucket: s3BucketName
}
s3.getSignedUrl('getObject', params, function (err, url) {
if (err) {
console.error(err)
next(err);
} else {
res.json({ url })
}
})
});