SpringBoot服務端上傳檔案
最近做一個小程式服務端模組支援,小程式涉及到了檔案上傳,之前架構組提供了一個統一上傳的介面給前端呼叫,因此沒有服務端需要開發的部分。
然而上線前一天,問題出現了,正式環境上傳檔案介面 不能提供給外網呼叫!需要通過服務端做中轉,臨危受命,緊急開發一個介面接收檔案,然後通過httpClient呼叫架構組的介面上傳檔案資料。
問題點如下:1.如果接收前端檔案 需要跟前端約定 2.httpClient請求 需要用連線池管理
為了更快解決,上網查了一些資料,瞭解到springBoot可以使用
upload(@RequestParam("file") MultipartFile file
接收檔案
之後寫http呼叫程式碼,構建請求物件
突然發現了一個問題,構造builder裡面檔案是用java.io.File型別的,但是springBoot接收的是MultipartFile,兩者需要轉換,不能直接拿來用,於是乎,又查了一些資料關於MultipartFile轉換成File,都是通過生成臨時檔案的方式,考慮到檔案上傳資料量還是挺大的,如果出現問題,臨時檔案沒有及時清除,對伺服器的磁碟記憶體會有很大壓力,因此該方案不可行。//檔案引數 MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.setContentType(ContentType.MULTIPART_FORM_DATA); builder.addPart("file", fileBody); builder.addPart("path", pathBody); builder.addPart("projectName", projectNameBody); builder.addPart("rename", reNameBody); post.setEntity(builder.build());
之後換了個方向,考慮http請求能不能直接傳輸MultipartFile,結果發現還真有,程式碼就改動了一行 然後問題解決:
httpClient連線管理器通過開源的構建了一個,設定了連線池大小,最大超時時間等等配置資料。完整程式碼如下://檔案引數 MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.setContentType(ContentType.MULTIPART_FORM_DATA); builder.addBinaryBody("file", file.getInputStream(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename()); builder.addPart("path", pathBody); builder.addPart("projectName", projectNameBody); builder.addPart("rename", reNameBody); post.setEntity(builder.build());
/**
* 上傳
*
* @param file
* @param projectName
* @param path
* @param reName
* @return
**/
public String uploadFileToOss(MultipartFile file, String projectName, String path, String reName) {
HttpResponse response = null;
HttpPost post = new HttpPost(businessConfigProperties.getFileUploadUrl());
try {
StringBody projectNameBody = new StringBody(projectName, ContentType.APPLICATION_JSON);
StringBody pathBody = new StringBody(path, ContentType.APPLICATION_JSON);
StringBody reNameBody = new StringBody(reName, ContentType.APPLICATION_JSON);
//檔案引數
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.setContentType(ContentType.MULTIPART_FORM_DATA);
builder.addBinaryBody("file", file.getInputStream(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename());
builder.addPart("path", pathBody);
builder.addPart("projectName", projectNameBody);
builder.addPart("rename", reNameBody);
post.setEntity(builder.build());
response = apacheHttpDnsClientBuilder.build().execute(post);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.OK.value()) {
HttpEntity resEntity = response.getEntity();
String resultStr = EntityUtils.toString(resEntity);
ResultMap<String> result = JSON.parseObject(resultStr, ResultMap.class);
LogUtil.log(LogUtil.EXCEPTION_HANDLER, Level.INFO, LogUtil.formatLog(KVJsonFormat.title
("uploadFileToOss").add("result", resultStr)));
if (Objects.toString(ResultMap.SUCCESS).equals(Objects.toString(result.get(ResultMap.CODE)))) {
return businessConfigProperties.getFileDownloadUrl() + "/" + result.get(ResultMap.DATA);
} else {
LogUtil.log(LogUtil.EXCEPTION_HANDLER, Level.ERROR, LogUtil.formatLog(KVJsonFormat.title
("uploadFileToOss fail").add("result", resultStr)));
throw new MiniProgramException(FILE_UPLOAD_FAIL);
}
} else {
LogUtil.log(LogUtil.EXCEPTION_HANDLER, Level.ERROR, LogUtil.formatLog(KVJsonFormat.title
("uploadFileToOss fail").add("statusCode", statusCode)));
throw new MiniProgramException(FILE_UPLOAD_FAIL);
}
} catch (Exception e) {
throw new MiniProgramException(FILE_UPLOAD_FAIL);
} finally {
if (response != null) {
EntityUtils.consumeQuietly(response.getEntity());
}
post.releaseConnection();
}
}
總結一下:專案管理流程出現了問題,前端也沒有及時提出這個問題,最後導致開發時間比較緊張,之前因為沒有接觸過這塊內容,因為unKnown感覺有點害怕,不過實際解決過程中,發現也沒有這麼困難,多去解決一些問題,在這個過程中肯定可以收收穫和成長
後記:踩了一個坑 專案環境執行一段時間之後 出現了這個提示Resolved exception caused by Handler execution: 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.
分析是因為上傳的檔案超過了1M,沒有配置檔案上傳的大小限制 預設限制1M