文件上傳是Java EE開發經常遇到的,文件上傳的方式有很多中方式
本次的上傳方式是基於commons-fileupload
1、文件上傳
Spring MVC框架的文件上傳是基於commons-fileupload 組件的文件上傳
SpringMVC對原有的組建上進行進一步的封裝,簡化了文件上傳代碼的實現
取消了不同上傳組件的編程差異
①、基於表單的文件上傳
標簽<input type="file" />就是一個輸入框和一個按鈕
<form action="<%=request.getContextPath()%>/upload" method="post" enctype="multipart/form-data"> <input type="file" name="img"><br> <input type="submit" value="submit"> </form>
對於基於表單的文件上傳不要忘記使用enctype屬性,並且將值設置為:multipart/form-data
同時將表單的提交方式設置為post
關於enctype:是指定數據表單的編碼方式
application/x-www-urlencoded:這是默認的編碼方式,它只處理表單域中的value屬性值
multipart/form-data:該編碼是以二進制流的方式處理表單數據,並將文件域指定文件的內容封裝到請求的參數里
text/plain:該編碼方式只有當表單的action屬性為mailto:URL的形式才使用,主要適用於直接通過表單發郵件的方式
②、MultipartFile接口
springmvc框架中上傳文件時將文件的相關信息及操作封裝到MultipartFile對象中
開發者只需要怕調用類型聲明模型的一個屬性即可對上傳文件進行操作。
該接口有以下的方法:
byte[] getBytes():以字節數組的形式返回文件內容
String getContentType():返回文件的內容類型
boolean isEmpty():判斷上傳文件是否為空
long getSize():返回文件的大小,單位字節
InputStream getInputStream():返回一個InputStream,從中讀取文件的內容
void transferTo(File var1):將上傳文件保存在目標目錄下
③、單個文件上傳
創建好一個工程,需要使用到的兩個jar是:

同時也將該兩個jar復制在tomcat的lib文件夾下,以免再開發的時候報錯!!!
再web.xml文件中可以為了防止中文亂碼進行相關的設定:
web.xml
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上傳頁面的設置:
file.jsp
<body> 上傳文件:<br> <form action="<%=request.getContextPath()%>/upload" method="post" enctype="multipart/form-data"> <input type="file" name="img"><br> <input type="submit" value="submit"> </form> </body>
上傳成功之后的跳轉頁面
show.jsp
<body>
success!!!
</body>
配置controller
FileController.java
@Controller public class FileController { @RequestMapping("/upload") public String upLoad(MultipartFile img) throws Exception { //存放的路徑 String path = "d:/images"; //獲取文件的原始名稱 String fileName = img.getOriginalFilename(); System.out.println(fileName); File file = new File(path,fileName); //文件上傳 img.transferTo(file); return "show"; } }
這里說一下:如果File的使用方法掌握比較好,可以進行使用File的方法,而不需要提前把所需要的文件夾創建好!!!
dispatcher-servlet.xml
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="controller"/>
<!--視圖解析-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="suffix" value=".jsp"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
</bean>
<!--文件上傳 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="104857600"/> <property name="maxInMemorySize" value="4096"/> </bean>
這里嚴重需要注意:文件上的配置id是固定的,DispatcherServlert中的值會和該id進行配對!!!
測試:

跳轉頁面:

查看本地:

文件存放位置問題:
由於path直接是本地的文件位置,再正常的業務中都是再服務器中,需要較多的費用,且指定文件夾的位置可能會造成不必要的后果!
此時將項目的文件設置只能安放在指定的工程文件加下,即項目下的某個文件夾:
修改controller
@RequestMapping("/upload") public String upLoad(MultipartFile img, HttpSession session) throws Exception { //存放的路徑 //String path = "d:/images"; String path = session.getServletContext().getRealPath("/images"); //獲取文件的原始名稱 String fileName = img.getOriginalFilename(); System.out.println(fileName); File file = new File(path,fileName); //文件上傳 img.transferTo(file); return "show"; }
測試的結果是:

此時用戶上傳的文件夾只能再本地工程的目錄中!!!
關於CommonsMultipartResolver:
上傳中文遇到亂碼的問題
上傳設置文件大小問題
......
配置文件中:
<bean id="multipartResolver" class="org.springframework.web.multipart.
commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="104857600"/> <property name="maxInMemorySize" value="4096"/> <property name="defaultEncoding" value="utf-8"></property> </bean>
maxInMemorySize:允許文件上傳的最大尺寸
maxUploadSize:最大的上傳文件大小(字節)
defaultEncoding:編碼方式
是否是空文件問題:
如果沒有選擇文件,后台中的img不是空的!!!
可進行打印測試!
可進行文件大小是否為0的測試在進行業務的實現
@RequestMapping("/upload") public String upLoad(MultipartFile img, HttpSession session) throws Exception { String path = session.getServletContext().getRealPath("/images"); if (img.getSize() > 0){ //獲取文件的原始名稱 String fileName = img.getOriginalFilename(); System.out.println(fileName); File file = new File(path,fileName); //文件上傳 img.transferTo(file);
return "show";
}
return "show";
}
指定文件類型
開發中可以根據需要進行指定文件的類型,根據判斷能否正常進行業務的實現
@RequestMapping("/upload") public String upLoad(MultipartFile img, HttpSession session) throws Exception { String path = session.getServletContext().getRealPath("/images"); if (img.getSize() > 0){ //獲取文件的原始名稱 String fileName = img.getOriginalFilename(); if (fileName.endsWith("jpg") || fileName.endsWith("txt")){ System.out.println(fileName); File file = new File(path,fileName); //文件上傳 img.transferTo(file); } } return "show"; }
此時的實現業務都很簡單
②、多文件上傳
再原有工程上進行多文件上傳的操作
新建前端添加頁面:
files.jsp
上傳文件:<br> <form action="<%=request.getContextPath()%>/uploads" method="post" enctype="multipart/form-data"> <input type="file" name="img"><br> <input type="file" name="img"><br> <input type="submit" value="submit"> </form>
controller實現
具體的邏輯沒有進行太多的實現!!!
@Controller public class FilesController { //上傳多個文件!! @RequestMapping("/files") public String Files(){ return "files"; } @RequestMapping("/uploads") public String uploads(@RequestParam MultipartFile [] img, HttpSession session) throws Exception { String path = session.getServletContext().getRealPath("/images"); for (MultipartFile imgs :img){ if (imgs.getSize() > 0){ String fileName = imgs.getOriginalFilename(); File file = new File(path,fileName); imgs.transferTo(file); } } return "show"; } }
此時值得說一下:
上文件的name都是統一的,后台既可以得到一個數組
再后台的參數中創建數組時,需要用@RequestParam注解進行指定,否則會報錯!!!
測試頁面:

查看本地的文件夾:

此時的文件都已經成功的上傳!!!
2、文件下載
①、文件下的實現方法
文件下載有兩種方法:
超鏈接下載
程序編碼進行下載
超鏈接下載實現簡單,但是暴露了下載文件的真是位置,並且只能下載存放在WEB應用程序所在的目錄下文件
程序編碼實現的下載可以增強安全的訪問機制,還可以從任意位置提供下載的數據
利用程序實現下載需要設置兩個報頭:
1、Web服務器需要告訴瀏覽器其所輸出的類型不是普通文本文件或HTML文件,而是一個保存再本地的
下載文件,還需要設置Content-Type的值為application/x-msdownload
2、Web服務器希望瀏覽器不直接處理響應的實體內容,而是由用戶選擇相應的實體內容保存到一個文件
中,還需要設置Content-Disposition報頭。
②、文件下載過程
前端下載頁面的顯示:
showDownFiles.jsp
<table>
<tr>
<td>文件名</td>
</tr>
<c:forEach items="${files}" var="f">
<tr>
<td><a href="<%=request.getContextPath()%>/down?filename=${f}">${f}</a></td>
</tr>
</c:forEach>
</table>
Controller實現:
package controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.*; import java.util.ArrayList; @Controller public class FileDownController { //顯示要下載的文件 @RequestMapping("/showDownFiles") public String show(HttpSession session, HttpServletRequest request, Model model){ //下載文件的位置 String reqlpath = session.getServletContext().getRealPath("/images"); File dir = new File(reqlpath); File files [] = dir.listFiles(); //獲取文件夾下的所有文件名 ArrayList<String> filaName = new ArrayList<>(); for (int i = 0;i<files.length;i++){ filaName.add(files[i].getName()); } model.addAttribute("files",filaName); return "showDownFiles"; } @RequestMapping("/down") public String down(@RequestParam String filename, HttpServletRequest request, HttpServletResponse response,HttpSession session){ //要下載的路徑 String aFilePath = null; //輸入流 FileInputStream in = null; //輸出流 ServletOutputStream out = null; try { //從文件夾中獲取文件 aFilePath = session.getServletContext().getRealPath("/images"); //設置文件下載使用的報頭 response.setHeader("Content-type","application/x-msdownload"); response.setHeader("Content-Disposition","attachment;filename=" + toUTF8String(filename)); //讀入文件 in = new FileInputStream(aFilePath + "\\" + filename); out= response.getOutputStream(); out.flush(); int aRead = 0; byte b [] = new byte[1024]; while ((aRead = in.read(b))!=-1 & in != null){ out.write(b,0,aRead); } out.flush(); in.close(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println("success"); return null; } //下載保存文件名的字符編碼轉換方法 public String toUTF8String(String str){ StringBuffer sb = new StringBuffer(); int len = str.length(); for (int i=0;i<len;i++){ //取出字符中的每個字符 char c = str.charAt(i); if(c >=0 && c <=255){ sb.append(c); }else { byte b []; try { b=Character.toString(c).getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); b=null; } for (int j = 0;j<b.length;j++){ int k = b[j]; if (k<0){ k&=255; } sb.append("%" + Integer.toHexString(k).toUpperCase()); } } } return sb.toString(); } }
測試:

點擊下載:


