ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Uppy XHRUpload Bundle 模式实战:单请求批量上传文件到自定义后端

Uppy XHRUpload Bundle 模式实战:单请求批量上传文件到自定义后端 前端UI组件后端【免费下载链接】uppyThe next open source file uploader for web browsers :dog:项目地址https://gitcode.com/gh_mirrors/up/uppy点击查看免费下载导读本文基于 Uppy 仓库中的 examples/xhr-bundle 示例完整讲解如何使用uppy/xhr-upload插件的bundle 模式将所有待上传文件打包进一次multipart/form-data 请求中发送到指定后端端点而不是为每个文件各发一次请求。你将学会 bundle 模式的适用场景、前后端完整可运行的实现方案、底层源码行为约束以及如何在本仓库中一键启动这个示例进行验证。一、bundle 模式是什么一次请求上传全部文件默认情况下XHRUpload插件会为每个文件单独发起一次 XHR 上传请求。而在bundle 模式下插件会把本次上传队列中的全部文件合并到一个请求里发出。原文对此的定位很清晰bundle 模式会让单次上传变慢一些因为一个大请求需要整体传输完成但服务端处理会简单很多——后端只需要解析一次 multipart 请求体即可不必为每个文件分别写路由、分别做鉴权或日志。它特别适合那些整批到达、整批处理的服务端架构。在仓库的示例中前端把bundle: true传给 XHRUpload 插件后一次POST http://localhost:9967/upload请求就会携带用户选择的所有文件见 examples/xhr-bundle/main.js服务端则用 Express multer 一次性接收并回显文件信息。二、前后端完整实现拆解2.1 前端Uppy Dashboard XHRUpload 配置示例前端入口 examples/xhr-bundle/main.js 展示了完整的装配方式import Uppy from uppy/core import Dashboard from uppy/dashboard import XHRUpload from uppy/xhr-upload import uppy/core/css/style.css import uppy/dashboard/css/style.css const uppy new Uppy({ debug: true, meta: { something: xyz }, }) uppy.use(Dashboard, { target: #app, inline: true, hideRetryButton: true, hideCancelButton: true, }) uppy.use(XHRUpload, { bundle: true, endpoint: http://localhost:9967/upload, allowedMetaFields: [something], fieldName: files, })关键配置项说明bundle: true开启 bundle 模式是本文的核心开关。endpoint上传目标地址示例指向本地 Express 服务的/upload路由。allowedMetaFields: [something]只允许something这个元数据字段随请求一起发送这是白名单机制防止其他 meta 字段被无差别提交。fieldName: files文件字段名。注意一个细节当bundle: true时插件在构造函数里会把默认fieldName自动改成files[]见 xhr-upload 源码多文件会以同名多次 append 的形式出现在 form-data 中示例显式指定为files也完全合法。服务端用upload.array(files)与之匹配。debug: true开启 Uppy 调试日志便于在浏览器控制台观察上传过程。meta: { something: xyz }在 Uppy 实例上预设全局元数据与allowedMetaFields配合演示元数据过滤。页面骨架 examples/xhr-bundle/index.html 提供了一个#app挂载点Dashboard 会以内联inline: true方式渲染在其中。2.2 后端Express multer 接收 multipart 批量上传服务端 examples/xhr-bundle/server.cjs 非常精简完整代码如下const app require(express)() const cors require(cors) const multer require(multer) const upload multer({ storage: multer.memoryStorage(), }) function uploadRoute(req, res) { res.json({ files: req.files.map((file) { delete file.buffer return file }), }) } app.use(cors()) app.post(/upload, upload.array(files), uploadRoute) app.listen(9967)逐段解读multer.memoryStorage()把上传文件暂存到内存而非磁盘配合接收后立即回显 JSON的演示场景最合适生产环境通常改用multer.diskStorage()落盘或直接转交对象存储。upload.array(files)以files为字段名接收多个文件。bundle 模式下前端一次请求携带全部文件因此这里必须是数组接收array而不是单文件中间件single。若前端使用默认的files[]字段名服务端则应相应改为upload.array(files[])。delete file.buffer响应前移除内存 Buffer避免把二进制数据序列化进 JSON。app.use(cors())示例前端由 Vite 提供默认端口 5173与后端 9967 端口不同源因此必须开启 CORS。app.listen(9967)端口需与前端endpoint中写的一致。响应体是 JSON{ files: [...] }每项含 multer 解析出的文件名、大小size、MIME 类型mimetype等元信息正好呼应 README 中responds with name and size as JSON的描述。上传成功后这些信息还会被 XHRUpload 插件作为upload-success事件的body回传给前端。2.3 启动脚本前后端并行运行示例的 package.json 用npm-run-all的run-p并行启动两个进程scripts: { start: run-p start:server start:client, start:client: vite, start:server: node server.cjs }start:clientVite 开发服务器提供前端页面与模块热更新start:servernode直接运行 Express 服务监听 9967。依赖方面示例通过 workspace 直接引用仓库内的uppy/core、uppy/dashboard、uppy/xhr-upload版本均为workspace:*服务端依赖express、cors、multer前端构建依赖vite。三、如何在本仓库运行这个示例按 README 的步骤必须在仓库根目录执行工作区模式会同时安装所有包的依赖corepack yarn install corepack yarn buildinstall会为包括本示例在内的所有 workspace 安装依赖build会构建各uppy/*包产物。完成后再于仓库根目录启动示例corepack yarn workspace example-xhr-bundle start运行后打开 Vite 输出的本地地址通常为http://localhost:5173页面标题为 Uppy example: XHRUpload to a single endpoint通过 Dashboard 选择多个文件点击上传浏览器只发起一次对http://localhost:9967/upload的 POST 请求可在 Network 面板确认Express 端会收到files数组下的全部文件并以 JSON 回显每个文件的名称与大小。四、源码级深入bundle 模式的底层行为与限制要真正用好 bundle 模式需要理解uppy/xhr-upload源码中的几个关键约束。以下均可在 packages/uppy/xhr-upload/src/index.ts 中找到依据。4.1 默认选项与 bundle 开关插件默认选项定义在 index.ts#L135-L146const defaultOptions { formData: true, fieldName: file, method: post, allowedMetaFields: true, bundle: false, headers: {}, timeout: 30 * 1000, limit: 5, withCredentials: false, responseType: , }其中bundle默认是false即默认逐文件上传fieldName默认是file但当bundle: true时构造函数会将其改写为files[]index.ts#L172与多文件 append 语义对应。4.2 构造期的硬性校验开启bundle: true时插件在构造阶段会做两项强制校验index.ts#L184-L194formData必须为truebundle 模式依赖 FormData 承载多个文件若同时设置formData: false会抛出opts.formData must be true when opts.bundle is enabled.headers不能是函数非 bundle 模式支持headers: (file) ({...})按文件动态生成请求头但 bundle 模式下多文件共用一次请求、无法逐文件定制因此函数形式会被拒绝opts.headers can not be a function when the bundle: true option is set.。4.3 上传阶段的限制不支持远程文件bundle 模式只支持本地文件。在#handleUpload中若检测到队列中存在远程文件file.isRemote即来自 Google Drive、Dropbox 等远程数据源会直接抛出Cant upload remote files when the bundle: true option is setindex.ts#L527-L534。4.4 取消语义只能整体取消不能单个取消bundle 请求把多个文件绑在同一个 XHR 上因此无法实现单文件取消。插件在install()时会通过individualCancellation: false告知 Uppy 相关能力index.ts#L548-L557并且只监听cancel-all事件来整体中止请求#uploadBundle中的this.uppy.once(cancel-all, abort)index.ts#L417-L426。这正好解释了示例前端为何设置hideRetryButton: true、hideCancelButton: true——由于不支持单文件取消/重试示例干脆隐藏了这些按钮避免用户产生歧义操作。4.5 请求体组装一份 FormData 装下所有文件createBundledUploadindex.ts#L359-L381负责组装请求体先写入通过allowedMetaFields过滤后的全局 meta 字段再遍历每个文件用setTypeInBlob将 Blob 的type更新为 Uppy 检测到的更精确的 MIME 类型后以fieldName默认files[]逐一 append。最后以单个 XHR/fetch 请求发送这就是一次请求传全部文件的实现本质。4.6 进度与成功回调事件广播到每个文件虽然只发一次请求但#getFetcher在上传进度和成功回调中会遍历文件列表为其中每一个文件发出upload-progress与upload-success事件index.ts#L227-L266并把响应 JSON示例中即{ files: [...] }作为body挂到每个文件上。因此 Dashboard 依然能逐个文件显示进度和成功状态用户体验上与逐文件上传基本一致。4.7 测试用例验证仓库测试 packages/uppy/xhr-upload/test/index.test.ts#L194-L231 专门验证了 bundle 模式向队列添加test.jpg、test2.jpg两个文件后断言服务端只收到 1 次 POSTexpect(postCount).toBe(1)且endpoint可以接收文件数组作为参数动态计算目标地址示例中拼出了.../upload-bundle/test.jpg,test2.jpg。对照非 bundle 测试同文件 L164-L192逐文件上传、POST 计数为 1 但 endpoint 只收单个文件可以清晰看到两种模式在请求数量与endpoint 入参形态上的差异——这正是本文开篇所述 bundle 模式本质的测试级证据。五、决策建议何时该用 bundle 模式综合 README 说明与源码行为可以归纳出明确的选型依据适合用 bundle 模式服务端希望一次请求收到整批文件例如批量入库、整批转码、签名/鉴权只做一次单请求传输带来的稍慢可以接受上传文件均为本地选择不涉及远程数据源不依赖单文件取消/重试、不依赖逐文件动态请求头。应该保持默认非 bundle模式需要并发上传大文件、需要逐文件进度与独立失败重试需要从 Google Drive、Dropbox 等远程源导入文件服务端需要按文件单独路由或单独鉴权。如果想进一步对比非 bundle 模式的其他写法可以参考仓库中 examples/xhr-php、examples/xhr-python 等同系列示例它们在服务端语言上各有侧重但请求形态与本文的 bundle 示例形成对照有助于完整理解uppy/xhr-upload的两类上传路径。赞分享前端UI组件后端【免费下载链接】uppyThe next open source file uploader for web browsers :dog:项目地址https://gitcode.com/gh_mirrors/up/uppy点击查看免费下载相关推荐PraisonAI Session 记忆持久化修复全解析让 Agent 跨会话记住对话历史PraisonAI Session 记忆持久化修复全解析让 Agent 跨会话记住对话历史 导读 在 PraisonAI 的多 Agent 应用中会话Se前端UI组件后端Apache APISIX loki-logger 插件实战批量推送请求日志到 Grafana Loki 并自定义日志格式Apache APISIX loki logger 插件实战批量推送请求日志到 Grafana Loki 并自定义日志格式 loki logger 是 ApaAPI网关后端云原生微服务Uppy与Express集成构建Node.js文件上传后端Uppy与Express集成构建Node.js文件上传后端 你是否在寻找一种简单高效的方式来为你的Web应用添加文件上传功能Uppy作为一款现代化的开源文件前端UI组件后端上一篇如何构建 FlexSearch 全文搜索库条件编译与多版本构建系统完全解析下一篇如何彻底告别聊天记录丢失3个步骤掌握个人数据管理工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表