【Javaweb----檔案上傳】
阿新 • • 發佈:2021-09-01
【Javaweb---檔案上傳】
一、準備工作
匯入包
<dependencies> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.8.0</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> </dependencies>
二、建立流程
1、使用類介紹
2、FileItem類
在HTML頁面input必須有name
<input type="file" name="filename">
表單如果包含一個檔案上傳輸入項的話,這個表單的enctype屬性必須設定為multipart/form-data
<%@ page contentType="text/html; charset=UTF-8" language="java" %> <html> <body> <h2>Hello World!</h2> </body> <%--通過表單上傳檔案 get:上傳檔案大小有限制 post:無限制 --%> <form action = "${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post"> 上傳使用者:<input type="text" name="username"><br/> <p><input type = "file" name="file1"></p> <p><input type = "file" name="file1"></p> <p><input type = "submit"> | <input type = "reset"></p> </form> </html>
3、ServletFileUpload類
ServletFileUpload負責處理上傳的檔案資料,並將表單中每個輸入項封裝成一個FileItem物件,在使用ServletFileUpload物件解析請求時需要DiskFileItemFactory物件。所以,我們需要在進行解析工作前構造好DiskFileItemFactory物件。通過ServletFileUpload物件的構造方法或setFileItemFactory()方法設定ServletFileUpload物件的fileItemFactory屬性。
4、程式碼編寫
FileServlet.java
package com.darkerg.servlet; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.UUID; public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //判斷上傳的檔案時普通表單還是帶檔案的表單 if (!ServletFileUpload.isMultipartContent(req)){ return;//終止方法執行,說明這是一個普通的表單,直接返回. } try { //建立上傳檔案的儲存路徑,建議在WEB-INF路徑下,安全,使用者無法直接訪問上傳的檔案. String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload"); File uploadFile = new File(uploadPath); if (!uploadFile.exists()){ uploadFile.mkdir();//建立這個目錄 } //快取,臨時檔案。 //臨時路徑,加入檔案超過了預期的大小,我們就把他放到一個臨時檔案中,過幾天自動刪除,或者提醒使用者轉存為永久。 String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp"); File file = new File(tmpPath); if (!file.exists()){ file.mkdir();//建立這個目臨時錄 } //處理上傳的檔案,一般都需要通過流來獲取,我們可以使用reqeust.getInputStream(),原生態的檔案上傳流獲取,十分麻煩 //但是我們都建議使用Apache的檔案上傳元件來實現,common-fileupload,它需要依賴與commons-io元件; //ServletFileUpload負責處理上傳的檔案資料,並將表單中每個輸入項分裝成一個FileItem物件, //在使用ServletFileUpload物件解析請求時需要DiskFileItemFactory物件。 //所以,我們需要在進行解析工作前構造好DiskFileItemFactory物件, //通過ServletFileUpload物件的構造方法或setFileItemFactory()方法 //設定ServletFileUpload物件的fileItemFactory屬性 //1.建立DiskFileItemFactory物件,處理檔案上傳路徑或者大小限制的; DiskFileItemFactory factory = new DiskFileItemFactory(); //通過這個工廠設定一個緩衝區,當上傳的檔案大於這個緩衝區的時候,將他放到臨時檔案中。 factory.setSizeThreshold(1024 * 1024);//緩衝區大小為1M factory.setRepository(file);//臨時目錄的儲存目錄,需要一個File //2.獲取ServletFileupload ServletFileUpload upload = new ServletFileUpload(factory); //監聽檔案上傳進度 upload.setProgressListener(new ProgressListener() { //pBytesRead:已經讀取到的檔案大小 //pContentLength:檔案大小 public void update(long pBytesRead, long pContentLength, int pItems) { System.out.println("總大小:"+pContentLength+"已上傳:"+pBytesRead); } }); //處理亂碼問題 upload.setHeaderEncoding("UTF-8"); //設定單個檔案的最大值 upload.setFileSizeMax(1024 * 1024 * 10); //設定總共能夠上傳檔案的大小 //1024 = 1kb * 1024 =1M * 10 = 10M upload.setSizeMax(1024 * 1024 * 10); //3.處理上傳的檔案 //把前端請求解析,封裝成一個FileItem物件,需要從ServletFileUpload物件中獲取 List<FileItem> fileItems = upload.parseRequest(req); for (FileItem fileItem : fileItems) { //判斷山川的檔案時普通的表單還是帶檔案的表單 if (fileItem.isFormField()){ //fileItem 每一個表單物件 //getFieldName指的是前端表單控制元件的name; String name = fileItem.getFieldName(); String value = fileItem.getString("UTF-8");//處理亂碼 System.out.println(name+":"+value); }else {//檔案 //=======================處理檔案========================= String uploadFileName = fileItem.getName(); //可能存在檔名不合法的情況 System.out.println("上傳的檔名:"+uploadFileName); if (uploadFileName.trim().equals("") || uploadFileName==null){ continue; } //獲得上傳的檔名 /images/girl/paojie.png String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1); //獲取檔案的字尾名 String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); /* 如果檔案字尾名fileExtName不是我們需要的就直接return,不處理,考蘇使用者檔案型別不對。 */ //可以使用UUID(唯一識別的通用碼),保證檔名唯一。 //UUID.randomUUID(),隨機生成一個唯一識別的通用碼。 //網路傳輸中的東西,都需要序列化。 //POJO,實體類,如果想要在多個電腦上執行,傳輸====>需要吧物件都序列化了 String uuidPath = UUID.randomUUID().toString(); //=======================存放地址========================= //存到那兒?uploadPath //檔案真實存在的路徑realPath String realPath = uploadPath + "/" + uuidPath; //給每個檔案建立一個對應的資料夾 File realPathFile = new File(realPath); if (!realPathFile.exists()){ realPathFile.mkdir(); } //=======================檔案傳輸========================= //獲得檔案上傳的流 InputStream inputStream = fileItem.getInputStream(); //建立一個檔案輸出流 //realPath = 真實的資料夾; //差了一個檔案;加上輸出檔案的名字+"/"+uuidFileName FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName); //建立一個緩衝區 byte[] buffer = new byte[1024 * 1024]; //判斷是否讀取完畢 int len = 0; //如果大於0說明還存在資料; while ((len=inputStream.read(buffer))>0){ fos.write(buffer,0,len); } //關閉流 fos.close(); inputStream.close(); } } } catch (FileUploadException e) { e.printStackTrace(); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
三、上傳的檔案在哪裡
通過Maven搭建的,我這邊在Tomcat目錄下的webapps中
通過其它方式搭建,可以尋找專案釋出後的路徑中尋找。