ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Sails 文件上传到 Amazon S3:使用 Skipper-S3 适配器实现流式上传

Sails 文件上传到 Amazon S3:使用 Skipper-S3 适配器实现流式上传 Sails 文件上传到 Amazon S3使用 Skipper-S3 适配器实现流式上传【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址: https://gitcode.com/gh_mirrors/sa/sails导读本文讲解如何在 Sails 应用中借助 Skipper 生态的skipper-s3文件上传适配器以流式方式将用户上传的文件直接传输到 Amazon S3 对象存储无需先将文件落盘到本地文件系统。读完本文你将掌握S3 桶的区域硬性要求、req.file(...).upload({...})的完整配置写法、上传回调与响应组织方式以及 Sails 内置 Skipper 底层流式处理机制与安全注意事项。背景Sails 的文件上传机制Sails 内置了名为 Skipper 的body parser它让流式文件上传变得非常简单——上传目标不局限于服务器本地磁盘还可以是 Amazon S3、MongoDB GridFS 或其他受支持的存储适配器参见 docs/concepts/File Uploads/File Uploads.md 中的整体介绍。这一机制在仓库源码中有直接体现在 lib/hooks/http/get-configured-http-middleware-fns.js 中默认的bodyParser中间件在未显式配置时会require(skipper)而 package.json 中skipper: ^0.9.5也确认了它是 Sails 运行时默认依赖。也就是说一个常规的 Sails 应用开箱即可在 action 中调用req.file()接收 multipart 上传。需要注意req.file()只在 HTTP 请求上下文中可用。在 lib/router/index.js 中Sails 为虚拟请求例如 socket.io 请求设置了req.file的 mock 实现直接返回 500 并提示 Streaming file uploads viareq.file()are only available over HTTP with Skipper.——因此 S3 上传同样仅适用于 HTTP 上传场景。前置条件S3 桶必须位于 US East (N. Virginia) 区域skipper-s3适配器存在一个容易踩坑的硬性约束你的 Amazon S3 bucket 必须创建在US East (N. Virginia)区域即区域代码us-east-1。如果桶创建在其他区域上传将无法工作AWS 会返回InvalidRequest错误。这是文档开篇就强调的关键前提见 docs/concepts/File Uploads/uploading-to-amazon-s3.md。在创建桶时务必选择该区域否则后续所有上传请求都会失败且错误信息来自 AWS 服务端排查成本较高。此外你还需要准备好 AWS 凭据一组拥有该桶写权限的Access Key与Secret Key即下文代码中的key与secret。安装 skipper-s3 适配器在 Sails 项目根目录执行npm install skipper-s3 --save该命令会把skipper-s3加入项目package.json的dependencies。它是 Skipper 生态中的一个blob receiver存储接收器负责把 Skipper 解析出的上传流写入 S3。在控制器中使用适配器上传安装完成后在任意 controller action 中通过req.file(字段名)拿到 Skipper Upstream再调用.upload()并传入 S3 配置。以下示例直接来自官方文档见 docs/concepts/File Uploads/uploading-to-amazon-s3.mduploadFile: function (req, res) { req.file(avatar).upload({ adapter: require(skipper-s3), key: S3 Key, secret: S3 Secret, bucket: Bucket Name }, function (err, filesUploaded) { if (err) return res.serverError(err); return res.ok({ files: filesUploaded, textParams: req.allParams() }); }); }配置项说明选项类型说明adapter((function))指定上传接收适配器这里为require(skipper-s3)返回的适配器构造器key((string))AWS Access Key ID用于鉴权secret((string))AWS Secret Access Key用于鉴权bucket((string))目标 S3 桶名称必须位于us-east-1区域.upload()的第二个参数是完成回调(err, filesUploaded)上传过程中出错时err非空此时应返回res.serverError(err)成功时filesUploaded是本次上传产生的文件描述数组可返回给前端使用示例中同时通过req.allParams()取回请求中的文本参数一并返回。req.allParams()由 lib/hooks/request/params.all.js 注入它合并了 query string、request body 与路由参数。关于安全硬编码凭据的提醒示例中的key/secret是占位写法。生产环境中切勿把 AWS 凭据硬编码进控制器代码更不要提交到版本库。建议将凭据放入 Sails 的环境变量或config/local.js该文件通常已被.gitignore忽略再在 action 中通过process.env或sails.config读取。从源码结构看Sails 的配置体系如config/local.js与环境变量天然支持这种注入方式。底层原理Skipper 如何流式处理上传理解req.file()的行为有助于排查 S3 上传问题。根据 docs/reference/req/req.file.md 的说明req.file(field)返回一个 SkipperUpstream表示来自指定字段如avatar的 multipart 文件上传。Upstream 本质上是一个 Node.js Readable 流object mode其中的每个对象都是一次传入的 multipart 文件上传流。Skipper 把所有文件上传都当作流处理。当 multipart 请求到达服务器时Skipper 并不会把临时文件写入磁盘而是只缓冲请求足够长的时间来运行你的应用代码让你插入一个兼容的 blob receiver在这里就是skipper-s3。如果某个字段的数据没有插入到任何 receiverUpstream 会达到其 high water mark缓冲区被刷新之后到达的字节将被忽略。底层实现上.upload()所做的工作就是把 Upstream 管道pipe到指定的 receiver 实例并在 Upstream 触发finish或error事件时执行回调。这套流式设计带来的好处是用户可以上传体积很大的文件而对内存与磁盘占用影响很小同时还能抵御利用 TMP 文件发起的拒绝服务攻击。文本参数必须在文件参数之前由于 Skipper 是流式处理multipart 请求体中所有文本参数必须位于任何文件参数之前。这样 Sails 可以在文件仍在上传时就开始执行你的 action 代码而不必等待上传全部完成这是为了避免 Express 系应用中常见的 body parser DDoS 漏洞。如果你通过req.allParams()或req.body读取表单文本字段时发现取不到值请先检查客户端提交顺序文本字段在前input typefile在后。从本地磁盘上传迁移到 S3作为对照Sails 默认不指定adapter时使用磁盘接收器skipper-disk文件会写入myApp/.tmp/uploads/目录可通过dirname选项自定义参见 docs/concepts/File Uploads/File Uploads.md。例如req.file(avatar).upload({ dirname: require(path).resolve(sails.config.appPath, assets/images) }, function (err, uploadedFiles) { if (err) return res.serverError(err); return res.json({ message: uploadedFiles.length file(s) uploaded successfully! }); });迁移到 S3 时你只需在.upload()的选项对象中把adapter换成require(skipper-s3)并提供key/secret/bucket即可把落盘目标整体替换为对象存储。两者共用同一套回调签名err, filesUploaded因此返回给前端的文件描述结构保持一致同时由于文件直接进入 S3也规避了将不可信文件存放在 Web 根目录下的安全隐患。安全注意事项不要信任请求中的 MIME 类型文件上传请求头里的 MIME 类型不可靠永远不要依赖它来判断文件真实内容。不自动病毒扫描Sails/Skipper 不会对上传做病毒扫描或异常检测。若你的应用允许用户互相上传、共享文件保护用户免受恶意文件侵害是你自己的责任。永远假设请求是恶意的进入服务器的任何请求都可能被伪造或伪装涉及文件存储的路径、命名与访问控制都要按不可信输入处理。完整实战流程小结在 AWS 控制台创建 S3 桶区域选择 US East (N. Virginia)us-east-1否则上传会报InvalidRequest准备拥有该桶写权限的 AWS Access Key / Secret Key在项目根目录执行npm install skipper-s3 --save在 controller action 中调用req.file(avatar).upload({ adapter: require(skipper-s3), key, secret, bucket }, callback)回调中处理err返回res.serverError与filesUploaded返回给前端并可通过req.allParams()一并返回文本参数生产环境将凭据收敛到环境变量或config/local.js避免硬编码。【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址: https://gitcode.com/gh_mirrors/sa/sails创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表