今天總結下Spring中的文件上傳與下載,在寫這篇博客以前,小編寫過一篇有關文件上傳下載的博文------React Native 上傳圖片至七牛雲存儲,該博文主要聊到採用React Native 框架如何將文件上傳到七牛雲存儲上,後端部分主要集成了七牛雲提供的API,但並無從底層講到文件上傳下載的基本原理,因此本篇博文儘可能彌補以前的不足,接下來,咱們一塊兒開始吧!html
就Java web 而言,對於文件上傳,前端瀏覽器提交一個文件,而後後端處理返回文件上傳成功或者失敗的結果;對於文件下載,不少狀況就是前端單擊某個按鈕或者點擊某個文字連接,而後瀏覽器就會自動將文件上傳到本地中。那麼這其中的原理是什麼呢?小編認爲,文件的上傳下載本質上是經過Java 提供的流API來處理的,在Servlet中咱們可使用Http相關的HttpServletResponse
對象將文件流輸出到瀏覽器,固然這涉及到咱們瀏覽器如何識別該流是一個文件仍是一個文本字符串的問題,因此文件上傳下載還提到了Http請求頭Mime類型的設置.前端
小編之前會想這麼一個問題,我如今會使用html表單來上傳一個文件,但當我使用一個框架的時候,我就不太明白其中的原理了。關於這個問題,小編認爲原理都是同樣的,最本質的,都是經過表單來提交文件上傳請求,也就是html中的<input type="file"/>
標籤,不管你框架怎麼封裝,底層就是一個表單。下面咱們講下如何Spring boot 來實現文件上傳下載,本示例前端部分採用簡單的html表單,沒有用到任何框架,簡單易懂。java
在Spring 框架中,對於文件上傳下載的支持是經過MultipartFile
接口來實現的,一個MultipartFile
就表示客戶端傳過來的一個文件,而一個MultipartFile[]
數組,則表示客戶端傳過來的多個文件,這在實現多文件上傳很是有用,固然了,經過該接口,你能夠獲取客戶端傳過來的文件的一些基本信息,好比文件名稱、文件大小等.固然你也可讓Spring限制客戶端傳過來文件的大小和類型(好比圖片文件png
仍是文本文件txt
),但這些功能的實現配置不在本文的範圍內。web
Spring MVC傳統的REST風格用法是經過@Controller
、@ResponseBody
和@RequestMapping
三個註解實現的,在Spring Boot 中,你只須要使用@RestController
和@RequestMapping
兩個註解便可,簡單示例以下:spring
/**
* 測試文件上傳與下載
*
* @author hjw
*
*/
@RestController
public class FileUploadCotroller {
@RequestMapping(value = "/upload.json", method = RequestMethod.POST)
public boolean fileUpload( MultipartFile file) throws IllegalStateException, IOException {
return false;
}
}
複製代碼
因爲Spring框架依賴了commons-fileupload
包,所以,咱們須要在Maven的pom.xml
文件中將該jar包引進來。json
pom.xml
後端
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
複製代碼
upload.html
數組
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="http://localhost:8081/upload.json" method="POST" enctype="multipart/form-data">
<input name="file" type="file"/>
<button type="submit">single submit</button>
</form>
</body>
</html>
複製代碼
FileUploadCotroller.java
瀏覽器
@RestController
public class FileUploadCotroller {
@RequestMapping(value = "/upload.json", method = RequestMethod.POST)
public boolean fileUpload( MultipartFile file) throws IllegalStateException, IOException {
if (file.getSize() == 0) {
return false;
}
System.err.println("文件是否爲空 : " + file.isEmpty());
System.err.println("文件的大小爲 :" + file.getSize());
System.err.println("文件的媒體類型爲 : " + file.getContentType());
System.err.println("文件的名字: " + file.getName());
System.err.println("文件的originName爲: " + file.getOriginalFilename());
File newFile = new File("C:\\Users\\hjw\\Desktop\\" + file.getOriginalFilename());
file.transferTo(newFile);
return true;
}
}
複製代碼
上面的html文件表單要設置表單的enctype
屬性爲enctype="multipart/form-data"
,而且<input/>
標籤的name
屬性值必須和後端接口的MultipartFile
參數名一致,也就是都是file
七牛雲存儲
文件下載前端很簡單,咱們直接使用一個<a><a/>
標籤便可。
download.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="http://localhost:8081/download.json">single download</a>
</body>
</html>
複製代碼
FileUploadCotroller.java
@RequestMapping(value="download.json")
public boolean download(HttpServletResponse res) throws IOException {
File file = new File("C:\\Users\\hjw\\Desktop\\design\\code\\project-1\\myapp\\src\\images\\seats\\bg1.png");
String fileName = "bg1.png";
res.setHeader("Content-Disposition", "attachment;filename=" + fileName);
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
os = res.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(file));
int i = bis.read(buff);
while (i != -1) {
os.write(buff, 0, buff.length);
os.flush();
i = bis.read(buff);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("success");
return false;
}
}
複製代碼
上面的文件下載採用流的形式進行傳輸,注意,要實現文件下載功能,咱們必須在響應頭中設置Http Header
的Content-Disposition
參數,該參數會激活瀏覽器的下載功能,並接受咱們傳輸的文件。
上面提到多文件上傳對應MultipartFile[]
數組,所以咱們只需改下後端的參數便可。
multiUpload.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="http://localhost:8081/multiFile.json" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple="multiple" value="請選擇多個文件"/>
<button type="submit">multi submit second</button>
</form>
</body>
</html>
複製代碼
FileUploadCotroller.java
@RequestMapping(value="multiFile.json",method=RequestMethod.POST)
public boolean multiFile(MultipartFile[] files) throws IllegalStateException, IOException {
if(files.length == 0) {
return false;
}
File file = null;
String path = "C:\\Users\\hjw\\Desktop\\";
for (int i = 0; i < files.length; i++) {
System.err.println("第" + i + "個文件的大小爲" + files[i].getSize());
System.err.println("第" + i + "個文件是否爲空" + files[i].isEmpty());
System.err.println("第" + i + "個文件的媒體類型爲" + files[i].getContentType());
System.err.println("第" + i + "個文件的文件名爲" + files[i].getName());
System.err.println("第" + i + "個文件的源文件名爲" + files[i].getOriginalFilename());
file = new File(path + files[i].getOriginalFilename());
files[i].transferTo(file);
}
return false;
}
複製代碼
注意咱們要設置html文件<input/>
標籤的multiple
屬性爲multiple="multiple"
,該屬性表示支持文件多選操做。同時,和單文件上傳相同,咱們的<input/>
標籤的name
屬性必須和後端的MultipartFile[]
參數名相同,即files
.
這些例子很簡單,屬於入門級別,固然文件上傳下載作的好並非這麼簡單的,只不過咱們平常項目並非對文件上傳下載功能要求很苛刻(好比迅雷),固然,若是你想作的高級一點,你可使用Java提供的文件隨機存取類RandomAccessFile
去實現斷點上傳和下載,斷點上傳下載的功能http也是有提供相應的支持的。 謝謝閱讀!