You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Localstack 3.0.2预签名URL上传S3对象时内容长度为0

问题分析与解决

核心问题是上传方式错误:预签名PUT URL要求直接上传文件的原始字节内容,而你用MediaType.MULTIPART_FORM_DATA的表单格式提交,导致LocalStack无法解析出有效文件内容,最终生成了空对象。

修正后的上传代码

替换原来的Groovy上传逻辑,直接将文件流作为请求体提交:

void putFileToPresignedUrl(Resource resource, String presignedUrl) {
    def decodedUri = URLDecoder.decode(presignedUrl, StandardCharsets.UTF_8.toString())
    def headers = new HttpHeaders().tap {
        // 根据文件实际类型设置Content-Type,比如text/plain、image/png,通用场景用二进制流即可
        setContentType(MediaType.APPLICATION_OCTET_STREAM)
    }
    // 直接传入文件输入流作为请求体,无需包装成表单
    def httpEntity = new HttpEntity<>(resource.inputStream, headers)

    rest.put(decodedUri, httpEntity)
}

额外检查点

  • 确认S3客户端/预签名器已正确配置LocalStack端点,比如设置endpointOverride为LocalStack的S3地址,签名版本用SIGNING_V4
  • 确保测试前已提前创建目标Bucket(LocalStack默认不会自动创建Bucket)
  • 验证传入的Resource确实有效:调用resource.exists()和resource.contentLength()确认文件存在且有内容

原因说明

S3的PutObject API(预签名PUT URL对应的接口)要求请求体就是文件的原始二进制数据。而多部分表单提交会在请求体中添加表单边界、字段名等额外结构,LocalStack接收到这类请求后,无法提取出实际的文件内容,因此返回200但存储了空对象。

内容的提问来源于stack exchange,提问作者Tomáš Mika

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:52:15