ARTICLE DETAIL

资讯详情

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

使用 Artillery 进行 HTTP 文件上传压测:基于 formData 与 fromFile 的完整实战指南

使用 Artillery 进行 HTTP 文件上传压测:基于 formData 与 fromFile 的完整实战指南 性能测试接口测试CLI【免费下载链接】artilleryThe complete load testing platform. Everything you need for production-grade load tests. Serverless distributed. Load test with Playwright. Load test HTTP APIs, GraphQL, WebSocket, and more. Use any Node.js module.项目地址https://gitcode.com/gh_mirrors/ar/artillery点击查看免费下载本指南以 Artillery 仓库中的 http-file-uploads 示例 为核心讲解如何在 Artillery 测试脚本中通过formData与fromFile完成 multipart/form-data 文件上传的压测包括配套 Express 文件接收服务器的搭建、测试脚本编写、随机文件轮换、上传文件清理以及底层源码实现原理。读完本文你将能够独立编写并运行一个可复用的 HTTP 文件上传负载测试场景。示例整体结构该示例位于仓库的 examples/http-file-uploads 目录包含四个核心组成部分文件作用app.js基于 Express Multer 的文件上传接收服务器监听 3000 端口file-uploads.ymlArtillery 测试脚本演示如何上传文件files/存放待上传的样例文件jpg / pdf / png 各一个uploads/服务器接收上传后存储文件的目录运行时生成package.json定义服务器启动、测试运行、上传目录清理等 npm 脚本搭建并启动文件接收服务器安装依赖示例自带了 Express 应用app.js先安装其依赖npm install安装完成后启动 HTTP 服务器npm run app:start该命令实际执行node app.js见 package.json 中的scripts定义启动后服务监听于http://localhost:3000/。服务器实现解析接收端服务器代码非常精简使用 multer 中间件处理 multipart 文件上传const express require(express); const app express(); const upload require(multer)({ dest: uploads/, preservePath: true }); const port 3000; app.post(/upload, upload.single(document), (req, res) { const { originalname, mimetype, size } req.file; res.json({ originalname, mimetype, size }); }); app.listen(port, () { console.log(App listening at http://localhost:${port}); });关键点Multer 将上传文件落盘到uploads/目录路由/upload接收字段名为document的单个文件upload.single(document)与测试脚本中formData.document.fromFile的字段名一一对应服务器响应返回originalname、mimetype、size三个 JSON 字段方便在压测脚本中通过capture断言上传是否成功。编写文件上传测试脚本示例测试脚本 file-uploads.yml 是理解 Artillery 文件上传用法的核心config: target: http://localhost:3000 phases: - duration: 10min arrivalRate: 25 # 通过 variables 定义待上传文件的文件名列表 # 这些文件放置在 /files 目录下。 variables: filename: - artillery-logo.jpg - artillery-installation.pdf - sre-fundamental-rules.png scenarios: - flow: # HTTP 服务器有一个 POST /upload 端点通过 document 字段接收文件 - post: url: /upload formData: document: # fromFile 属性指示 Artillery 上传指定文件 # 若文件无法读取场景会报 ENOENT 错误。 fromFile: ./files/{{ filename }}该脚本展示了文件上传压测的三大要素1. 负载配置config.phasesduration: 10minarrivalRate: 25表示持续 10 分钟、每秒启动 25 个虚拟用户模拟每分钟 1500 次上传请求的中等压力。arrivalRate是 Artillery 的固定到达率模型实际请求量还受每个场景内请求数量与思考时间影响。2. 随机文件轮换variablesvariables.filename定义了 3 个文件名Artillery 在每次场景运行时从列表中随机抽取一个值与模板语法{{ filename }}结合后拼出完整路径./files/artillery-logo.jpg、./files/artillery-installation.pdf、./files/sre-fundamental-rules.png从而实现每次上传随机文件的效果。相比固定上传同一文件这种随机化更贴近真实用户的上传行为也避免服务器缓存造成测试失真。若需要按权重分配文件名可使用weightedPick类权重机制进一步扩展。3. multipart 表单字段formDatadocument是表单字段名需与服务器端upload.single(document)严格对应fromFile指定待上传文件路径。路径是相对于测试脚本所在目录解析的见下文源码分析示例中即examples/http-file-uploads/files/路径支持模板表达式因此可配合变量实现动态选择文件。运行压测确保服务器已启动后在示例目录执行artillery run file-uploads.yml运行期间 Artillery 会按phases配置的速率持续向POST /upload发起 multipart 上传请求。仓库集成测试中的 http-file-upload.yml 展示了更完整的用法——同一请求中混合普通文本字段与多个fromFile文件字段formData: name: Artillery logo: fromFile: ./files/artillery-logo.jpg guide: fromFile: ./files/{{ filename }}即formData中既可以有纯文本字段name也可以有多个fromFile文件字段字段名各不相同即可。集成测试还通过afterResponse钩子对上传响应进行断言校验见 http-file-upload-processor.js可用于功能验证类场景。清理上传目录测试过程中上传的文件会持续写入服务器的uploads/目录为方便清理示例提供了npm run uploads:clean该命令实际执行del-cli uploads/* !uploads/.keep见 package.json删除目录内所有上传文件但保留.keep占位文件。也可在服务器代码中接入定期清理策略如按时间轮转目录避免压测期间磁盘被写满。底层实现原理formData 与 fromFile 是如何工作的从源码层面深入理解这两个关键字有助于排查路径、字段、Content-Type 等问题。HTTP 引擎中的 multipart 处理文件上传由 HTTP 引擎 engine_http.ts 实现。当检测到params.formData时引擎按以下流程处理创建FormData实例new FormData()承载 multipart 数据遍历formData的每个字段先对值执行模板插值template(v, context)若字段值是一个普通对象_.isPlainObject存在contentType时将其作为该字段的 Content-Type 选项例如 JSON 字段指定application/json存在fromFile时将fromFile路径解析为绝对路径基于context.vars.$scenarioFile所在目录即测试脚本所在目录并用fs.createReadStream(absPath)创建文件读取流作为字段值存在value时直接取该值作为普通文本字段内容调用acc.append(k, V, options)将字段追加到 multipart body最终作为请求体发送。相对路径的解析基准注意fromFile的路径是相对测试脚本文件.yml所在目录解析的而非当前工作目录。示例脚本位于 examples/http-file-uploads/file-uploads.yml因此./files/{{ filename }}指向examples/http-file-uploads/files/。如果你的测试脚本放在其他目录务必确认files/的相对位置正确。Content-Length 与 ENOENT 行为上传的文件流由 Node 的fs.createReadStream创建若文件不存在读取流会触发ENOENT错误——这正是原文档提示如果文件无法读取该场景将报告 ENOENT 错误的原因引擎支持通过setContentLengthHeader: true显式设置Content-Length头见 types.d.ts 与 engine_http.ts对某些严格要求长度头的服务器很有用设置失败时引擎仅记录 debug 日志不会中断测试。类型与 Schema 定义在 types.d.ts 中formData被定义为Recordstring, unknown注释明确其为 Multipart form (multipart/form-data)e.g. for file uploadssetContentLengthHeader为可选布尔值。配置 schema 侧engines/http.js也预留了formData的校验入口。单元测试佐证仓库的 HTTP 引擎单元测试 engine_http.test.js 专门覆盖了formDatamultipart 场景验证了普通文本字段activity、type、location以Content-Disposition: form-data发送带contentType: application/json的对象字段会附加对应 Content-Type字段值支持模板变量{{ activity }}、{{ climate.temperature }}等。这从测试层面印证了formData三种字段形态纯文本、valuecontentType、fromFile文件流的完整语义。常见问题与排查思路问题现象可能原因与处理场景报 ENOENTfromFile路径错误或文件不存在检查路径相对测试脚本所在目录是否正确服务器收不到文件formData字段名与服务器如upload.single(document)不一致中文/特殊字符文件名乱码检查服务器端 multipart 解析配置与原文件名编码上传文件堆积占满磁盘定期执行npm run uploads:clean或按轮转策略管理uploads/目录需要为文件字段指定 Content-Type使用contentType属性源码见 engine_http.ts小结通过 http-file-uploads 示例可以掌握 Artillery 进行文件上传压测的完整链路Express Multer 接收服务器搭建、formDatafromFile脚本编写、variables随机文件轮换、模板路径插值以及setContentLengthHeader等进阶选项。结合 engine_http.ts 的源码实现与单元测试即可在实际项目中复现并对抗文件上传接口的性能瓶颈。赞分享性能测试接口测试CLI【免费下载链接】artilleryThe complete load testing platform. Everything you need for production-grade load tests. Serverless distributed. Load test with Playwright. Load test HTTP APIs, GraphQL, WebSocket, and more. Use any Node.js module.项目地址https://gitcode.com/gh_mirrors/ar/artillery点击查看免费下载相关推荐MWPBench 数学应用题统一评测基准数据集构成、双引擎评测流程与模糊判分源码解析unilm/mathscaleMWPBench 数学应用题统一评测基准数据集构成、双引擎评测流程与模糊判分源码解析unilm/mathscale MWPBenchMath Word性能测试接口测试CLI使用 React Hook Form 与 FormData 实现 Multipart 文件上传Refine 实战指南使用 React Hook Form 与 FormData 实现 Multipart 文件上传Refine 实战指南 在 React 应用中向服务器上传图片前端企业应用Qogir-theme打造优雅Linux桌面GTK扁平设计主题完全指南Qogir theme打造优雅Linux桌面GTK扁平设计主题完全指南 Qogir theme是一款专为Linux桌面打造的扁平设计GTK主题它能瞬间提升上一篇lightweight-charts 价格刻度Price Scale完全指南坐标映射、模式切换与 overlay 刻度管理下一篇Cytoscape.js 元素类名闪烁 flashClass 详解临时高亮与视觉反馈的实现原理与实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表