我有一个endpoint,它将图像文件上传到服务器,然后上传到S3。
当我在本地主机上运行时,MultipartFile字节大小正确,并且上传成功。
然而,当我将它部署到EC2实例时,上传的文件大小不正确。
控制器代码
@PostMapping("/{id}/photos")
fun addPhotos(@PathVariable("id") id: Long,
@RequestParam("file") file: MultipartFile,
jwt: AuthenticationJsonWebToken) = ApiResponse.success(propertyBLL.addPhotos(id, file, jwt))
在 PropertyBLL.addPhotos
方法中,打印 file.size 会导致大小错误。
实际文件大小是649305字节,但是当上传到我的prod服务器时,它读取为1189763字节。
我做了另一个测试,我将上传的文件写入服务器,以便进行比较。
在十六进制编辑器中上载文件的前n个字节:
EFBFBD50 4E470D0A 1A0A0000 000D4948 44520000 03000000 02400802 000000EF BFBDCC96 01000000 0467414D 410000EF BFBD0BEFBF BD610500 00002063 48524D00 007A2600
原始文件的前n个字节:
< code > 89504 e47 0 d0a 1a 0a 00000000d 49484452 000000300 000000240 08020000 00 b5 cc 96 0100000000 0467414d 410000 B1 8f 0 bfc 61 05000000 20634852 4d 000007 a 260000000 fa 00
它们看起来都包含文本“PNG ”,并且还有结尾EXtdate:modify/create标记。
根据请求,addPhoto的核心内容如下:
val metadata = ObjectMetadata()
metadata.contentLength = file.size
metadata.contentType = "image/png"
LOGGER.info("Uploading image of size {} bytes, name: {}", file.size, file.originalFilename)
val request = PutObjectRequest(awsProperties.cdnS3Bucket, imageName, file.inputStream, metadata)
awsSdk.putObject(request)
当我在本地运行web服务器时,这一点很有效。imageName只是一个自定义生成的名称。还有其他涉及hibernate模型的代码,但并不相关。
更新
这似乎是与 Https/api 代理相关的。当我点击EC2节点的http url时,它工作正常。但是,当我通过代理到 EC2 节点的 api 代理 (https://api.thedomain.com) 时,它会失败。我将继续沿着这条路走下去。
用于实现 Kenny Cason 解决方案的 CloudFormation 模板代码段:
MyApi:
Type: AWS::Serverless::Api
Properties:
BinaryMediaTypes:
- "multipart/form-data"
抱歉,但许多评论毫无意义<代码>文件。size将返回上传文件的大小(以字节为单位),而不是请求的大小(是的,由于不同的过滤器,可能会使用其他信息和大小的增加来增强)。Spring不能只是神奇地将PNG文件的大小增加一倍(在您的情况下,在您发送的任何文件上再添加大约600kb的信息)。虽然我相信你知道你在做什么,你给我们的数字确实是正确的,但对我来说,所有证据都指向人为错误……请仔细检查,在所有情况下,你确实上传了相同的文件。
您最初是如何获得649305字节的?谁给了你那个号码?是你的代码,还是你实际上查看了磁盘上的文件,看看它有多大?在这种情况下,压缩讨论有意义的唯一方法是,如果649305字节是本地运行时文件的大小已经压缩(磁盘上的实际大小为1189763字节),并且实际上,由于某种原因,在部署到AWS时未启用压缩,并且您收到了完整的未压缩文件(我们甚至不知道您如何部署它...它真的和当地一样吗?在这两种情况下,您是否正在运行独立.jar?您是否正在将 .war 部署到 AWS?在这两种情况下,您是否真的在同一容器和容器版本中运行应用程序,或者您可能在本地运行Tomcat,在AWS上运行Jetty?等等等等)。您是否确定您的Postman请求没有搞砸,并且您没有意外发送其他内容(或比您想象的更多)?
编辑:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sandbox</groupId>
<artifactId>spring-boot-file-upload</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.sandbox;
import static org.springframework.http.ResponseEntity.ok;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@SpringBootApplication
public class Application {
public static void main(final String[] arguments) {
SpringApplication.run(Application.class,
arguments);
}
@RestController
class ImageRestController {
@PostMapping(path = "/images")
ResponseEntity<String> upload(@RequestParam(name = "file") final MultipartFile image) {
return ok("{\"response\": \"Uploaded image having a size of '" + image.getSize() + "' byte(s).\"}");
}
}
}
这个例子是用Java编写的,因为它放在一起的速度更快(环境是一个简单的Java环境,部署了独立的.jar - 没有额外的配置或任何东西,除了服务器端口在5000
上)。无论哪种方式,您都可以通过向 http://test123456.us-east-1.elasticbeanstalk.com/images 发送POST
请求来亲自尝试一下。
这是我的邮差请求和使用您提供的图像的响应:
在我的AWS EB实例上,一切看起来都很好,所有的数字加起来都和预期的一样。如果你说你的设置听起来很简单,那么不幸的是我和你一样困惑。我只能假设,到目前为止,您已经共享了更多内容(然而,我怀疑这个问题与Spring Boot有关……那么它更有可能与您的AWS配置/设置有关)。
经过更多的调试,我发现当我直接发布到EC2实例时,一切都按预期工作。我们的主 API 和公有 API URL 通过 Amazon 的 API Gateway 服务发出代理请求。出于某种原因,此服务将数据转换为 Base64,而不仅仅是传递原始二进制数据。
我在这里找到了更新API网关以传递二进制数据的文档。
我使用的是多部分/表单数据
的内容类型值。不要忘记在启用二进制支持的API设置中添加它。
最后,不要忘记部署您的api更改...
它现在像预期的那样工作。
我正在用Spring Boot 2.1.3(使用标准的Tomcat嵌入式web服务器)开发一个endpoint来上载图像,我想限制多部分上载的大小。我可以通过以下属性轻松完成此操作: 但是我总是得到Spring无法捕获的500,因为Tomcat正在抛出异常并且请求无法到达我在RestController中的代码。 我的ExceptionHandler是这样的,但无论注释中出现什么异常,它显然都不起
我试图创建一个页面,用户可以张贴图像及其细节。现在,当我测试来自postman的spring boot服务时,我能够成功地在服务中获取文件。当我试图从angular5中做同样的事情时,多部分文件在服务中没有被识别,并且总是得到空数组。 我的角服务代码如下 } 我已经尝试添加标头,如multipart/form-data,并将其设置为un定义。无论哪种方式,我都收到了错误。在发布到这里之前,我已经广
我正在尝试将图像作为广告中的字符串字段上传,但当将文件添加到正文时,我遇到了这个错误:“异常”:“org.springframework.web.multipart.support.MissingServletRequest estPartException”,“消息”:“所需的请求部分'file'不存在”。我在这里寻找有关此问题的答案,但没有任何帮助。我将很高兴得到任何帮助。 我的控制器: 我的
Im使用Spring Boot,并希望使用控制器接收多部分文件上传。当发送文件时,我一直得到错误415不支持的内容类型响应,并且控制器从未到达 我尝试在HTML/JSP页面和使用RESTTemplate的独立客户端应用程序中使用Form:Action发送。所有尝试的结果都是一样的 从multipart文档看来,边界参数必须添加到multipart上载,但这似乎与控制器接收不匹配 我的控制器方法设置
关于Spring MVC应用程序中的多部分文件上传问题,我已经看到了很多关于stackoverflow的答案。我一步一步地确保我不会重复别人犯过的错误。 这是我的表格 在pom文件中我有依赖项 因此,当我停在调试器中时,request对象显示文件已被接收,甚至存储在jBoss临时文件夹中,我并不感到惊讶。 你能指出Spring看不到上传的文件我会错过什么吗?
您可以使用基于浏览器的上传(不是多部分上传)中的内容长度范围字段来限制文件大小:http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html 你怎么能在多部分上传中限制它?我正在使用EvaporateJS。