使用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
相关产品推荐
相关产品推荐

