Spring Boot文件上傳示例(Ajax和REST)
本文介紹如何使用Ajax請求在Spring Boot Web應用程序(REST結構)中上傳文件。
本文中使用的工具:
- Spring Boot 1.4.3.RELEASE
- Spring 4.3.5.RELEASE
- Thymeleaf
- jQuery (webjars)
- Maven
- Embedded Tomcat 8.5.6
- Google Chrome瀏覽器
1. 項目結構
一個標準的Maven項目結構。如下圖所示 -
2. 項目依賴
聲明一個額外的jQuery webjar依賴關系,適用於HTML格式的Ajax請求。
文件:pom.xml
```xml
4.0.0
<groupId>com.yiibai</groupId> <artifactId>spring-boot-file-upload</artifactId> <packaging>jar</packaging> <version>1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.3.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- hot swapping, disable cache for template, enable live reload --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>2.2.4</version> </dependency> </dependencies> <build> <plugins> <!-- Package as an executable jar/war --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
## 3.文件上傳
為了支持Ajax請求和響應,最簡單的解決方案返回一個ResponseEntity。
以下示例演示了上傳文件的三種可能方式:
1. 單文件上傳 - `MultipartFile`
2. 多文件上傳 - `MultipartFile []`
3. 將文件上傳到模型 - [email protected]`
*文件:RestUploadController.java*
```java
package com.yiibai.controller;
import com.yiibai.model.UploadModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
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;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@RestController
public class RestUploadController {
private final Logger logger = LoggerFactory.getLogger(RestUploadController.class);
//Save the uploaded file to this folder
private static String UPLOADED_FOLDER = "D://temp//";
//Single file upload
@PostMapping("/api/upload")
// If not @RestController, uncomment this
[email protected]
以上示例的簡單模型 - @ModelAttribute
,文件:UploadModel.java -
package com.yiibai.model;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
public class UploadModel {
private String extraField;
private MultipartFile[] files;
public String getExtraField() {
return extraField;
}
public void setExtraField(String extraField) {
this.extraField = extraField;
}
public MultipartFile[] getFiles() {
return files;
}
public void setFiles(MultipartFile[] files) {
this.files = files;
}
@Override
public String toString() {
return "UploadModel{" +
"extraField=‘" + extraField + ‘\‘‘ +
", files=" + Arrays.toString(files) +
‘}‘;
}
}
Java
視圖文件
多個文件上傳的HTML表單。文件:upload.html -
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<h2>Spring Boot多文件上傳示例(使用AJAX)</h2>
<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
<input type="text" name="extraField"/><br/><br/>
<input type="file" name="files"/><br/><br/>
<input type="file" name="files"/><br/><br/>
<input type="submit" value="提交" id="btnSubmit"/>
</form>
<h1>Ajax提交結果:</h1>
<pre>
<span id="result"></span>
</pre>
<script type="text/javascript" src="webjars/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
HTML
5. jQuery - Ajax請求
jQuery通過表單#id
獲取表單,並通過Ajax請求發送多部分(multipart
)表單數據。文件:resources/static/js/main.js -
$(document).ready(function () {
$("#btnSubmit").click(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
fire_ajax_submit();
});
});
function fire_ajax_submit() {
// Get form
var form = $(‘#fileUploadForm‘)[0];
var data = new FormData(form);
data.append("CustomField", "This is some extra data, testing");
$("#btnSubmit").prop("disabled", true);
$.ajax({
type: "POST",
enctype: ‘multipart/form-data‘,
url: "/api/upload/multi",
data: data,
//http://api.jquery.com/jQuery.ajax/
//http://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
processData: false, //prevent jQuery from automatically transforming the data into a query string
contentType: false,
cache: false,
timeout: 600000,
success: function (data) {
$("#result").text(data);
console.log("SUCCESS : ", data);
$("#btnSubmit").prop("disabled", false);
},
error: function (e) {
$("#result").text(e.responseText);
console.log("ERROR : ", e);
$("#btnSubmit").prop("disabled", false);
}
});
}
Js
6. 異常處理程序
要處理來自Ajax請求的異常,只需擴展ResponseEntityExceptionHandler
並返回一個ResponseEntity
。文件:RestGlobalExceptionHandler.java -
package com.yiibai.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.servlet.http.HttpServletRequest;
//http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling
@ControllerAdvice
public class RestGlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(MultipartException.class)
@ResponseBody
ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity(new CustomError("0x000123", "Attachment size exceeds the allowable limit! (10MB)"), status);
//return new ResponseEntity("Attachment size exceeds the allowable limit! (10MB)", status);
// example
//return new ResponseEntity(ex.getMessage(), status);
//return new ResponseEntity("success", responseHeaders, HttpStatus.OK);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
}
Java
7. 運行演示
使用默認的嵌入式Tomcat的啟動Spring Boot命令:mvn spring-boot:run.
。
訪問:http://localhost:8080/
,選擇幾個文件並單擊提交以觸發ajax請求。
提示:打開目錄:
F:/temp
應該能看到上傳的文件。
Spring Boot文件上傳示例(Ajax和REST)