Spring MVC 中的文件上傳 和 文件下載
文章目錄
- Spring MVC 中的文件上傳 和 文件下載
- 1. Spring MVC 中的文件上傳
- 2. Spring MVC 中的文件下載
- 3. 總結:
- 4. 最后:
1. Spring MVC 中的文件上傳
文件上傳是:瀏覽器端向服務器發送文件,最終服務器將文件保存到服務器上
文件上傳需要添加如下依賴,注意:使用 Spring MVC 6版本,不需要添加以下依賴:
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.5</version>
</dependency>
前端頁面:
注意:
文件上傳必須是 post 請求,因為文件是大數據。get 請求不夠
文件上傳的form標簽中必須使用 enctype=“multipart/form-data”
enctype是用來設置請求頭的內容類型的,默認值是: enctype=“application/x-www-form-urlencoded”
文件上傳的組件是: 文件上傳:<input type="file" name="fileName">
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>文件上傳與下載</title>
</head>
<body>
<h1>文件上傳下載</h1>
<hr><h2>測試</h2>
<!--文件上傳,大文件,一定要用 post 請求才行-->
<!--文件上傳表單-->
<form th:action="@{/fileup}" method="post" enctype="multipart/form-data">文件:<input type="file" name="fileName"/><br><input type="submit" value="上傳">
</form>
<br></body>
</html>
重點是:form表單采用post請求,enctype是multipart/form-data,并且上傳組件是:type=“file”
web.xml文件:
注意:如果你用的是:Spring6 ,那么需要在web.xml 文件的 DispatcherServlet中進入如下的配置:
<multipart-config>
<!--設置單個支持最大文件的大小-->
<max-file-size>102400</max-file-size>
<!--設置整個表單所有文件上傳的最大值-->
<max-request-size>102400</max-request-size>
<!--設置最小上傳文件大小-->
<file-size-threshold>0</file-size-threshold>
</multipart-config>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><!-- 字符編碼過濾器--><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 前端控制器--><servlet><servlet-name>DispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup><multipart-config><!--設置單個支持最大文件的大小--><max-file-size>10240000</max-file-size><!--設置整個表單所有文件上傳的最大值--><max-request-size>10240000</max-request-size><!--設置最小上傳文件大小--><file-size-threshold>0</file-size-threshold></multipart-config></servlet><servlet-mapping><servlet-name>DispatcherServlet</servlet-name><!-- 除了 jsp 頁面其他的都走這個--><url-pattern>/</url-pattern></servlet-mapping><!-- 添加一個過濾器,這個過濾器是springmvc提前寫好的,直接用就行了,這個過濾器可以幫助你將請求POST轉換成PUT請求/DELETE請求--><!-- 同時注意:該過濾器一定要在字符編碼過濾器后面配置,不然,先設置的話,可能會出現獲取到的請求數據是亂碼--><filter><filter-name>HiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>HiddenHttpMethodFilter</filter-name><!-- 表示任意的 請求--><url-pattern>/*</url-pattern></filter-mapping></web-app>
重點:在DispatcherServlet配置時,添加 multipart-config 配置信息。(這是Spring6,如果是Spring5,則不是這樣配置,而是在springmvc.xml文件中配置:CommonsMultipartResolver)
SpringMVC6中把這個類已經刪除了。廢棄了。
文件上傳的 Controller 代碼編寫:
package com.rainbowsea.springmvc.controller;import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;import javax.lang.model.element.VariableElement;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.UUID;@Controller
public class FileController {@RequestMapping(value = "/fileup",method = RequestMethod.POST)public String fileup(@RequestParam("fileName")MultipartFile multipartFile, HttpServletRequest request) throws Exception {// 獲取請求參數的名字String name = multipartFile.getName();System.out.println(name); // fileName (前端 文件上傳: <input type="file" name="fileName"><br> )// 獲取的是文件真實的名字String originalFilename = multipartFile.getOriginalFilename();System.out.println(originalFilename); // xiaomu// 接下來就是看在 Java SE 當中的IO 功底了// 一邊讀,一邊寫//讀什么?寫什么// 讀客戶端傳過來的文件,寫倒服務器上// 輸入流InputStream in = multipartFile.getInputStream(); // 輸入流,負責讀客戶端的文件BufferedInputStream bis = new BufferedInputStream(in); // 封裝成帶有緩沖區的輸入流// 輸出流//BufferedOutputStream 文件的路徑 = new BufferedOutputStream((new FileOutputStream("文件的路徑")));ServletContext application = request.getServletContext();String realPath = application.getRealPath("/upload");File file = new File(realPath);// 文件不存在,就創建,存在不創建if(!file.exists()) {file.mkdirs();}File destFile = new File(file.getAbsoluteFile() + "/" + originalFilename);//BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFile));// 可以采用UUID來生成文件名,防止服務器上傳文件時產生覆蓋BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file.getAbsolutePath() + "/" + UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."))));// 一邊讀一邊寫byte[] bytes = new byte[1024 * 10];int readCount = 0;while ((readCount = bis.read(bytes))!=-1) {bufferedOutputStream.write(bytes,0,readCount);}bufferedOutputStream.flush();bufferedOutputStream.close();bis.close();return "ok";}//@RequestMapping(value = "/fileup", method = RequestMethod.POST)/* public String fileUp(@RequestParam("fileName") MultipartFile multipartFile, HttpServletRequest request) throws IOException {String name = multipartFile.getName();System.out.println(name);// 獲取文件名String originalFilename = multipartFile.getOriginalFilename();System.out.println(originalFilename);// 將文件存儲到服務器中// 獲取輸入流InputStream in = multipartFile.getInputStream();// 獲取上傳之后的存放目錄File file = new File(request.getServletContext().getRealPath("/upload"));// 如果服務器目錄不存在則新建if(!file.exists()){file.mkdirs();}// 開始寫//BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file.getAbsolutePath() + "/" + originalFilename));// 可以采用UUID來生成文件名,防止服務器上傳文件時產生覆蓋BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file.getAbsolutePath() + "/" + UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."))));byte[] bytes = new byte[1024 * 100];int readCount = 0;while((readCount = in.read(bytes)) != -1){out.write(bytes,0,readCount);}// 刷新緩沖流out.flush();// 關閉流in.close();out.close();return "ok";}*/
}
最終測試結果:
注意: 上傳文件時,文件起名采用UUID。以防文件覆蓋。
2. Spring MVC 中的文件下載
文件下載是:將服務器當中的文件,下載到本地客戶端當中
前端頁面:
<!--文件下載-->
<a th:href="@{/download}">文件下載</a>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>文件上傳與下載</title>
</head>
<body>
<h1>文件上傳下載</h1>
<hr><h2>測試</h2><!--文件下載-->
<h1>下載</h1>
<a th:href="@{/download}">文件下載</a></body>
</html>
文件下載核心程序,使用ResponseEntity:
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;import javax.lang.model.element.VariableElement;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.UUID;@Controller
public class FileController {@GetMapping("/download")public ResponseEntity<byte[]> downloadFile(HttpServletRequest request) throws IOException {File file = new File(request.getServletContext().getRealPath("/upload") + "xiaomu.jpeg");// 創建響應頭對象HttpHeaders httpHeaders = new HttpHeaders();// 設置響應內容類型httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);// 設置下載文件的名稱httpHeaders.setContentDispositionFormData("attachment",file.getName());// 下載文件ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(Files.readAllBytes(file.toPath()), httpHeaders, HttpStatus.OK);return entity;}
}
效果:
3. 總結:
- 文件上傳:form表單采用post請求,enctype是multipart/form-data,并且上傳組件是:type=“file”
- 上傳文件時,文件起名采用UUID。以防文件覆蓋。
4. 最后:
“在這個最后的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回復是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮斗。感謝你們,我們總會在某個時刻再次相遇。”