文件上傳
1:完成一個文件上傳的功能
index.jsp
注意更換form表單的enctype
enctype就是encodetype就是編碼類型的意思。
multipart/form-data是指表單數據有多部分構成,既有文本數據,又有文件等二進制數據的意思。
需要注意的是:默認情況下,enctype的值是application/x-www-form-urlencoded,不能用於文件上傳,只有使用了multipart/form-data,才能完整的傳遞文件數據。
application/x-www-form-urlencoded不是不能上傳文件,是只能上傳文本格式的文件,multipart/form-data是將文件以二進制的形式上傳,這樣可以實現多種類型的文件上傳。
下面是擴展:
一、關於HTML <form> 標簽的 enctype 屬性
application/x-www-form-urlencoded:在發送前編碼所有字符(默認)
multipart/form-data: 不對字符編碼,或在使用包含文件上傳控件的表單時,必須使用該值。
text/plain:空格轉換為 "+" 加號,但不對特殊字符編碼。
二、enctype:規定了form表單在發送到服務器時候編碼方式,有如下的三個值。
1、application/x-www-form-urlencoded。默認的編碼方式。但是在用文本的傳輸和MP3等大型文件的時候,使用這種編碼就顯得 效率低下。
2、multipart/form-data 。 指定傳輸數據為二進制類型,比如圖片、mp3、文件。
3、text/plain。純文體的傳輸。空格轉換為 “+” 加號,但不對特殊字符編碼。

1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html> 4 <html> 5 <head> 6 <meta charset="UTF-8"> 7 <title>文件上傳</title> 8 </head> 9 <body> 10 <form action="FileServlet" method="POST" enctype="multipart/form-data"> 11 <table> 12 <tr> 13 <td> 14 name: 15 </td> 16 <td> 17 <input name="user"> 18 </td> 19 </tr> 20 <tr> 21 <td> 22 password: 23 </td> 24 <td> 25 <input name="pwd"> 26 </td> 27 </tr> 28 <tr> 29 <td> 30 </td> 31 <td> 32 <input type="file" name="file"> 33 </td> 34 </tr> 35 <tr> 36 <td></td> 37 <td> 38 <input type="submit" value="上傳"> 39 </td> 40 </tr> 41 </table> 42 </form> 43 </body> 44 </html>
FileServlet.java
注意我這里用版本是3.0
@MultipartConfig 這個注解很重要 表示當前serlvet支持文件操作

1 package com.web; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.FileWriter; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.io.OutputStream; 9 import javax.servlet.ServletException; 10 import javax.servlet.annotation.MultipartConfig; 11 import javax.servlet.annotation.WebServlet; 12 import javax.servlet.http.HttpServlet; 13 import javax.servlet.http.HttpServletRequest; 14 import javax.servlet.http.HttpServletResponse; 15 import javax.servlet.http.Part; 16 17 @WebServlet("/FileServlet") 18 @MultipartConfig 19 public class FileServlet extends HttpServlet { 20 private static final long serialVersionUID = 1L; 21 22 23 24 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 25 doPost(request, response); 26 } 27 28 29 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 30 31 request.setCharacterEncoding("utf-8"); 32 response.setCharacterEncoding("utf-8"); 33 response.setContentType("text/html;utf-8"); 34 35 //接收參數 36 //文件描述 37 String name=request.getParameter("name"); 38 String pwd=request.getParameter("password"); 39 /*String files=request.getParameter("file"); 40 System.out.println("文件描述:"+files);*/ 41 //接收文件 42 43 Part part=request.getPart("file"); 44 //文件大小 45 //input中的name的屬性名稱 46 long size=part.getSize(); 47 String inputNmae=part.getName(); 48 System.out.println("文件大小:"+size); 49 System.out.println("input中的name的屬性名稱:"+inputNmae); 50 51 52 //獲得上傳的文件名稱 53 //獲取報頭文件描述 54 String header=part.getHeader("Content-Disposition"); 55 56 //返回f字符所在的位置 57 int idx=header.lastIndexOf("filename:\\"); 58 //filename="xxx.xxxx";xxx.xxx的位置是idx+10~header.length()-1; 59 String fileName=header.substring(idx+10,header.length()-1); 60 System.out.println("獲得文件上傳的名稱:"+header); 61 System.out.println(fileName); 62 System.out.println("f字符所在的位置:"+idx); 63 System.out.println("header:"+header.length()); 64 65 //獲得文件內容 66 InputStream inputStream=part.getInputStream(); 67 68 69 //獲得文件上傳的路徑 70 String path=this.getServletContext().getRealPath("/uploadFile"); 71 System.out.println("獲得文件上傳的路徑:"+path); 72 73 //取得上傳數據的文件名 74 int fString=fileName.lastIndexOf("\\"); 75 String saveFile=fileName.substring(fString+1); //獲取你的文件名 76 77 //如果file不存在,在這個路徑下創建文件 78 File file=new File(path); 79 if (!file.exists()) { 80 file.mkdirs(); 81 } 82 83 84 OutputStream fileWriter=new FileOutputStream(file+"\\"+saveFile); 85 System.out.println(fileWriter.toString()); 86 byte[] b=new byte[1024]; 87 int len=0; 88 while((len=inputStream.read(b))!=-1) { 89 fileWriter.write(b,0,len); 90 } 91 fileWriter.close(); 92 } 93 }
2:完成多個文件上傳的功能
index.jsp
前端的寫法和上面相差不大

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>文件上傳</title> </head> <body> <form action="FilesServlet" method="POST" enctype="multipart/form-data"> <table> <tr> <td> name: </td> <td> <input name="user"> </td> </tr> <tr> <td> password: </td> <td> <input name="pwd"> </td> </tr> <tr> <td> </td> <td> <input type="file" name="file"> </td> </tr> <tr> <td></td> <td> <input type="submit" value="上傳"> </td> </tr> </table> </form> </body> </html>
FileServlet.java
首先導入兩個jar
commons-fileupload-1.3.1.jar(依賴下面那個)
commons-io-1.3.2.jar

1 package com.web; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 import java.util.List; 9 import javax.servlet.ServletException; 10 import javax.servlet.annotation.MultipartConfig; 11 import javax.servlet.annotation.WebServlet; 12 import javax.servlet.http.HttpServlet; 13 import javax.servlet.http.HttpServletRequest; 14 import javax.servlet.http.HttpServletResponse; 15 import org.apache.commons.fileupload.FileItem; 16 import org.apache.commons.fileupload.FileUploadException; 17 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 18 import org.apache.commons.fileupload.servlet.ServletFileUpload; 19 20 @WebServlet("/FilesServlet") 21 @MultipartConfig 22 public class FilesServlet extends HttpServlet { 23 private static final long serialVersionUID = 1L; 24 25 26 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 27 doPost(request, response); 28 } 29 30 31 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 32 request.setCharacterEncoding("utf-8"); //請求的編碼 33 response.setCharacterEncoding("utf-8"); //響應的編碼 34 response.setContentType("text/html;utf-8"); //數據顯示時的編碼 35 36 37 //得到上傳文件的目錄,將上傳文件保存於WEB-INF目錄下,不允許外界直接訪問,保證上傳文件的安全 38 String realPath= this.getServletContext().getRealPath("/upload"); 39 System.out.println("文件存放的位置:"+realPath); 40 //設置臨時目錄,上傳文件大於緩沖區則先放於臨時目錄中 41 String tempPath="E:\\tempPath"; 42 System.out.println("臨時文件的存放位置:"+tempPath); 43 44 45 //判斷存放上傳文件的目錄是否存在(不存在創建) 46 File file=new File(realPath); 47 if(!file.exists()) { 48 System.out.println("目錄不存在!創建目標目錄"); 49 file.mkdir(); 50 } 51 52 //判斷臨時目錄是否存在(不存在則創建) 53 File file2=new File(tempPath); 54 if(!file2.exists()) { 55 System.out.println("臨時文件目錄不存在!創建臨時文件目錄"); 56 file2.mkdir(); 57 } 58 59 /** 60 * 使用Apache文件上傳組件處理文件上傳步驟 61 * 62 */ 63 //1.設置環境:創建一個 64 DiskFileItemFactory factory=new DiskFileItemFactory(); 65 66 //設置上傳文件的臨時目錄 67 factory.setRepository(file2); 68 69 //2.操作核心類 70 ServletFileUpload upload=new ServletFileUpload(factory); 71 72 //解決上傳編碼的問題 73 upload.setHeaderEncoding("utf-8"); 74 75 //3.判斷enctype:判斷提交上來的數據是否是表單提交上傳表單的數據 76 if(!upload.isMultipartContent(request)) { 77 System.out.println("不是文件,終止"); 78 //按照傳統方式獲取數據 79 return; 80 } 81 82 //==獲取輸入像=== 83 //限制單個上傳文件的大小(5M) 84 upload.setFileSizeMax(1024*1024*4); 85 //限制總上傳文件大小(10M) 86 upload.setSizeMax(1024*1024*6); 87 88 //4.使用ServletFileUpload解析器上傳數據,解析結果返回的是一個List<FileItem>集合,每一個FileItem對應一個Form表單的輸入項 89 try { 90 List<FileItem> parseParameter = upload.parseRequest(request); 91 for (FileItem fileItem : parseParameter) { 92 //如果fileItem中封裝的是普通輸入項的數據(輸出名,值) 93 if(fileItem.isFormField()) { 94 String common=fileItem.getFieldName(); 95 String commonValue=fileItem.getString("utf-8"); 96 System.out.println("普通屬性:"+common+": "+commonValue); 97 }else { 98 //如果fileItem中封裝的是上傳文件,得到上傳的文件名稱 99 String FileName=fileItem.getName(); 100 //多個文件上傳有輸入框有空的異常處理 101 if (FileName==null ||FileName.trim().equals("")) { 102 continue; //為空則退出那一次循環, 第一個沒輸入則跳過可以繼續輸入第二個 103 } 104 105 //注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt 106 //處理上傳文件的文件名的路徑,截取字符串只保留文件名部分。//截取留最后一個"\"之后,+1截取向右移一位("\a.txt"-->"a.txt") 107 FileName=FileName.substring(FileName.lastIndexOf("\\")+1); 108 //拼上上傳路徑。存放路徑+上傳的文件 109 String filePath =realPath+"\\"+FileName; 110 111 //構造輸入輸出流 112 InputStream inputStream=fileItem.getInputStream(); //獲取fileItem的上傳文件的輸入流 113 OutputStream outputStream=new FileOutputStream(filePath); //創建一個文件輸入流 114 115 116 //創建一個緩沖區 117 byte[] b=new byte[1024]; 118 //判斷輸入流中的數據是否已經讀完標識 119 int len=-1; 120 //循環將輸入流讀入到緩沖區當中,(len=in.read(buffer))!=-1就表示in里面還有數據 121 while((len=inputStream.read(b))!=-1) { //沒數據則返回-1 122 //使用FileOutputStream輸出流將緩沖區的數據寫入到指定的目錄(savePath+"\\"+filename)當中 123 outputStream.write(b,0,len); 124 } 125 126 //關閉流 127 inputStream.close(); 128 outputStream.close(); 129 //刪除臨時文件 130 Thread.sleep(3000); 131 fileItem.delete(); //刪除處理文件上傳時生成的臨時文件 132 System.out.println("文件上傳成功!!"); 133 } 134 135 } 136 } catch (FileUploadException | InterruptedException e) {e.printStackTrace();} 137 138 139 140 } 141 142 }
需要注意的是:注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt