【原文鏈接】:https://blog.tecchen.xyz ,博文同步發布到博客園。
由於精力有限,對文章的更新可能不能及時同步,請點擊上面的原文鏈接訪問最新內容。
歡迎訪問我的個人網站:https://www.tecchen.xyz 。
最近項目里面有個需求,要上傳圖片到阿里雲的OSS服務。所以需要寫個上傳圖片的接口給前端。
這個簡單的接口本來就給分配了1個工時,感覺也蠻簡單的。但編碼過程中遇到了好幾個問題,現在一一記錄下來,避免再次踩坑。
- 1、圖片不能超過1M
報錯信息:
org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
分析原因:
圖片大小超過了最大限制大小1048576 bytes=1MB,在org.springframework.boot.autoconfigure.web.MultipartProperties
中可以看到默認的maxFileSize為1MB。
解決方案:
在application.properties中配置
spring.http.multipart.maxFileSize = 10MB
- 2、圖片不能超過10M,連接重置
報錯信息:
org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (10559924) exceeds the configured maximum (10485760)
前端報錯:
Status:(failed)net::ERR_CONNECTION_RESET
分析原因:
請求大小超過了最大限制大小10485760 bytes=10MB,在org.springframework.boot.autoconfigure.web.MultipartProperties
中可以看到默認的maxRequestSize為10MB。
解決方案:
@RestControllerAdvice
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class MultipartExceptionConfigHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
@ExceptionHandler(MultipartException.class)
public MsCommonResult handleMultipartException(MultipartException icEx, HttpServletRequest request) {
logger.warn("請求業務報錯 uri: {}, message: {} ", request.getRequestURI(), icEx.getMessage());
return MsCommonResult.fail("禁止上傳大文件到服務器");
}
}
配置ExceptionHandler后,但是並沒有返回給前端400的狀態碼。繼續研究后注意到org.apache.coyote.http11.AbstractHttp11Protocol
的maxSwallowSize為2097152=2MB。
繼續解決:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
// -1 means unlimited
((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
}
});
return tomcat;
}
至此,前台收到返回,返回信息如下:
HTTP/1.1 400
X-Application-Context: ms.maker.company:8071
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 05 Dec 2018 09:37:58 GMT
Connection: close
{"result":500,"detail":"禁止上傳大文件到服務器","data":null}
- 3、Linux服務器返回413:Request Entity too large
報錯信息:
<html>
<head><title>413 Request Entity Too Large</title></head>
<body bgcolor="white">
<center><h1>413 Request Entity Too Large</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
分析原因:
圖片大小超過1M時,提示該信息。經研究nginx的client_max_body_size默認大小為1m。
解決方案:
在http/server/location段配置client_max_body_size: 10m即可。
- 4、返回JSON,IE9及低版本接受返回后,提示文件下載
原因:
后台響應的Content-Type為“application/json”,IE瀏覽器不識別。
將返回的數據由對象轉為json字符串,瀏覽器竟然可以自動識別解析。
解決方案:
方案一:
@PostMapping(value = "/aliyunOssUpload", produces = "text/html;charset=UTF-8")
public String aliyunOssUpload(@RequestParam("file") MultipartFile uploadFile)
方案二:
@PostMapping(value = "/aliyunOssUpload")
public String aliyunOssUpload(@RequestParam("file") MultipartFile uploadFile, HttpServletResponse response) {
response.setContentType("text/html;charset=UTF-8");
}
方案三:
@PostMapping(value = "/aliyunOssUpload")
public String aliyunOssUpload(@RequestParam("file") MultipartFile uploadFile, HttpServletResponse response) {
response.setHeader("Content-Type", "text/html;charset=UTF-8");
}