将存储在 S3 存储桶中的文件直接下载到 React 客户端,而不是通过 Node.js 服务器

Posted

技术标签:

【中文标题】将存储在 S3 存储桶中的文件直接下载到 React 客户端,而不是通过 Node.js 服务器【英文标题】:Download file stored in S3 bucket directly to React client, instead of passing through Node.js server 【发布时间】:2021-11-21 13:49:21 【问题描述】:

this one from heroku 之类的文章表明,可以在自己的 Node 服务器中签署请求并上传大文件直接从客户端到 S3,但我还没有找到类似的解决方案下载大文件直接从 S3 到客户端。

有关我正在尝试做的事情的更多信息:


我正在使用托管在 Heroku 上的 Node js 服务器构建一个 React Web 应用程序。用户创建和编辑音频文件,然后将其存储在 S3 存储桶中。

在接下来的会话中,音频必须再次从 S3 存储桶加载到用户的浏览器中。为此,Web 应用程序向节点 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 开发工具包(完全切断服务器),因为有人告诉我这是不好的做法,并且可能会暴露您的环境变量。

有没有办法安全可靠地将我的 s3 存储桶中的大文件直接下载到 React 客户端?

【问题讨论】:

【参考方案1】:

您可以在您的 node.js 服务器上生成一个presigned URL,以授予对 s3 对象的访问权限,将该 URL 发送到您的 React 应用程序并直接从 React 应用程序下载文件。

请务必注意,预签名 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 )
        
    )

);

【讨论】:

以上是关于将存储在 S3 存储桶中的文件直接下载到 React 客户端,而不是通过 Node.js 服务器的主要内容,如果未能解决你的问题,请参考以下文章

如何在不下载文件的情况下搜索amazon S3存储桶中的文件内容

如何将 Kinesis 流存储到 S3 存储桶中特定文件夹结构中的 S3 存储

复制同一 Amazon S3 存储桶中的文件

将 cloudfront 通配符 CNAME 子域路由到 s3 存储桶中的文件夹

如何使用angular js将aws s3文件复制到同一个存储桶中的特定文件夹

AWS S3 文件上传但存储桶中的文件没有大小?