You need to enable JavaScript to run this app. Locust编写文件上传压测任务时报400错误的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

Locust编写文件上传压测任务时报400错误的问题排查

故障定位与修正方案

核心问题点

  • 最核心触发报错的原因:手动硬编码multipart/form-data的边界值、Content-Length请求头。Locust底层基于requests库实现请求,当同时传递表单字段data和文件参数files时,库会自动生成与实际请求体完全匹配的边界标识、计算准确的请求体长度;手动写死的参数和实际发送的报文不匹配,会导致服务端解析表单时出现流截断,直接触发“Unexpected end of Stream”的报错。
  • 表单字段值中的"是HTML转义的双引号字符,实际传递给后端的内容不是预期的JSON结构,会造成字段校验异常。
  • 本地打开的文件句柄没有做自动释放处理,高并发场景下会出现文件读取不全、请求流不完整的问题。

修正后的可运行代码

from locust import task, HttpUser

class FileUploadTask(HttpUser):
    @task
    def constraintsuploaddoc(self):
        # 移除手动硬编码的content-type、content-length头,交由底层请求库自动生成
        headersc = {
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept': '*/*'
        }
        # 替换HTML转义字符为正常双引号,保证blobText为合法JSON结构
        payload = {
            'blobText': '{"ID": 3, "FileClass": "LogicsticsConstraints", "FileDescriptor": "test", "FieldName": "lookup.csv"}'
        }
        # 使用上下文管理器打开文件,自动释放文件句柄
        with open(r"C:\Perffiles\lookup.csv", "rb") as file_handle:
            files = [
                ('File', ('lookup.csv', file_handle, 'text/csv'))
            ]
            rupload = self.client.put(
                "/api/v1/FileUpload/Upload",
                data=payload,
                files=files,
                verify=False,
                headers=headersc,
                name="constraintsuploaddoc"
            )

        if rupload.status_code == 200:
            rupload.success()
        else:
            rupload.failure(f"上传失败,状态码{rupload.status_code},返回详情:{rupload.text}")

压测优化注意事项

  • 带文件上传的请求中,绝对不要手动指定Content-Type为multipart/form-data,也不要硬编码边界值,否则会100%出现表单解析失败的问题。
  • 测试用的文件内容建议在任务初始化阶段就预加载到内存,避免每次请求都执行磁盘IO、反复开关文件句柄,既可以提升压测场景的并发性能,也能规避文件读取不完整的异常。
  • 如需自定义请求边界值,必须保证边界标识和组装出来的请求体完全匹配,否则服务端无法正确拆分多表单结构。

内容的提问来源于stack exchange,提问作者Nagarjuna Pillappa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.01 13:15:04