SpringMVC之檔案上傳/下載
學習一個框架少不了學習檔案上傳和下載,原理來說上傳和下載都是基本二進位制流的轉換,所以搞清楚了這一點就很容易理解上傳和下載了
在使用springMVC進行系統實現時,springMVC預設的解析器裡面是沒有加入對檔案上傳的解析的,這可以方便我們實現自己的檔案上傳。但如果你想使用springMVC對檔案上傳的解析器來處理檔案上傳的時候就需要在spring的applicationContext裡面加上springMVC提供的MultipartResolver的申明。這樣之後,客戶端每次進行請求的時候,springMVC都會檢查request裡面是否包含多媒體資訊,如果包含了就會使用MultipartResolver進行解析,springMVC會使用一個支援檔案處理的MultipartHttpServletRequest來包裹當前的HttpServletRequest,然後使用MultipartHttpServletRequest就可以對檔案進行處理了。
一.檔案上傳
1.引入依賴包
檔案上傳需要額外引入包分別是
- commons-fileupload-1.3.1.jar
- commons-io-2.4.jar
2.配置jsp頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<metacharset="utf-8" >
<title>使用者登入</title>
</head>
<body>
<%--檔案上傳的話需要enctype="multipart/form-data"--%>
<sf:formmodelAttribute="user"method="post"enctype="multipart/form-data">
使用者名稱:<sf:inputpath="username"/><sf:errorspath="username"/>
<br>
密碼:<sf:inputpath="password"/><sf:errorspath="password"/>
<br>
暱稱:<sf:inputpath="nickname"/><sf:errorspath="nickname"/>
<br>
<%--這裡設定檔案上傳--%>
檔案:<inputtype="file"name="file">
<inputtype="submit"value="提交">
</sf:form>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
3.配置相應的控制器
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@Validated User user, BindingResult br, Model model,@RequestParam("file") MultipartFile file){
if (br.hasErrors()){
return "user/login";
}
//分別獲取的是變數名file---檔案型別---檔名
System.out.println(file.getName()+"---"+file.getContentType()+"---"+file.getOriginalFilename());
try {
if (!file.isEmpty()){
//使用StreamsAPI方式拷貝檔案
Streams.copy(file.getInputStream(),new FileOutputStream("E:/temp/"+file.getOriginalFilename()),true);
}
} catch (IOException e) {
System.out.println("檔案上傳失敗");
e.printStackTrace();
}
System.out.println(user.toString());
return "user/login";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
至此單個檔案上傳完成.
4.多檔案上傳
多檔案上傳很簡單,只需要把引數改為陣列就可以了
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@Validated User user, BindingResult br, Model model,@RequestParam("file") MultipartFile[] file){
if (br.hasErrors()){
return "user/login";
}
//這裡對檔案進行遍歷
for (MultipartFile mul:file){
//分別獲取的是變數名file---檔案型別---檔名
System.out.println(mul.getName()+"---"+mul.getContentType()+"---"+mul.getOriginalFilename());
try {
if (!mul.isEmpty()){
Streams.copy(mul.getInputStream(),new FileOutputStream("E:/temp/"+mul.getOriginalFilename()),true);
}
} catch (IOException e) {
System.out.println("檔案上傳失敗");
e.printStackTrace();
}
}
System.out.println(user.toString());
return "user/login";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
二.檔案下載
下載需要把檔案轉換成二進位制流,然後讓客戶端讀取這個二進位制流寫入到本機,這樣就實現了下載功能.那麼現在就要想兩個問題:1.怎麼把檔案寫成二進位制流? 2.怎麼把讓客戶端相應,開始下載?
答案;
- 寫成二進位制流可以用之前匯入的上傳元件提供的方法:
FileUtils.readFileToByteArray(file)
- 讓瀏覽器響應,則需要設定相應的httpHeader了,並且利用spring提供的ResponseEntity把返回值設定為header和響應內容
1.建立控制器程式碼
@RequestMapping(value = "/download",produces = "application/octet-stream;charset=UTF-8")
public ResponseEntity<byte[]> download() throws IOException {
// 指定檔案,必須是絕對路徑
File file = new File("E:/temp/me-bg.jpg");
// 下載瀏覽器響應的那個檔名
String dfileName = "1.jpg";
// 下面開始設定HttpHeaders,使得瀏覽器響應下載
HttpHeaders headers = new HttpHeaders();
// 設定響應方式
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 設定響應檔案
headers.setContentDispositionFormData("attachment", dfileName);
// 把檔案以二進位制形式寫回
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
2.測試下載
訪問指定的控制器就能觸發下載了
3.補充
有時候下載下來的檔案會出現被壓縮現象,也就是之前的格式都不存在了.解決辦法為配置SpringMVC的messageConverter如下:
<beanclass="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<propertyname="messageConverters">
<list>
<beanclass="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
</list>
</property>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
在SpringBoot中和fastjson一起使用可以如下:
本質上和xml配置是一樣的,注入的時候有些轉換器都有預設處理型別,所以沒必要再次配置
@Bean
public HttpMessageConverters customConverters() {
//fastjson處理訊息轉換
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
/*
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
*/
fastConverter.setFastJsonConfig(fastJsonConfig);
//檔案下載使用ByteArrayHttpMessageConverter處理
ByteArrayHttpMessageConverter byteArrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
byteArrayHttpMessageConverter.setDefaultCharset(Charset.forName("UTF-8"));
/*
//ByteArrayHttpMessageConverter預設處理請求型別就是APPLICATION_OCTET_STREAM
List<MediaType> byteMediaTypes = new ArrayList<>();
byteMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
byteArrayHttpMessageConverter.setSupportedMediaTypes(byteMediaTypes);
*/
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(fastConverter);
converters.add(byteArrayHttpMessageConverter);
return new HttpMessageConverters(converters);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
另外關於檔名亂碼,可以使用URLEncoder轉換下即可解決
String filename = URLEncoder.encode(file.getName(),"UTF-8");
- 1
- 1