1. 文件上傳
瀏覽器在上傳的過程中是將文件以 二進制的流 的形式提交到服務器端.
1 準備一個form表單,裏面有一個上傳,form表單的類型必需是multipart/form-data
2 準備一個上傳的Servlet,到後臺接收傳過來的普通表單數據 與 文件(二進制)
3 導入相應的FileUpload jar包 (commons-fileupload-1.2.2.jar ,commons-io-1.4.jar)
重要:上傳時,我們表單的請求類型必需設置成multipart/form-data . 上傳的method必需是POST的
完成文件上傳重要方法:fileItem.write(File file);
FileItemd對象就是從request中獲得數據對象,通過調用它的write把其中的數據寫入到磁盤文件(File file)
常見問題及其解決方案:
1. 上傳文件對象封裝----CFile對象 ,可以解決 多個文件上傳 及其對應屬性的屬性很多問題。
2. FileUtil.java 工具類 雖然可以完成上傳 但是 拿不到普通表單字段值,文件上傳後,我們拿到不到上傳的文件的數據。
解決辦法:準備兩個容器(就是集合),然後一個容器裝普通表單,另一個容器裝上傳的文件數據。把這個容器交給工具類,工具類拿到相應的數據後將數據放回到容器中。
1. 項目整體架構:
2. register.jsp代碼
<body> <form action="UploadServlet" method="post" enctype="multipart/form-data"> 用戶名:<input type="text" name="username"/><br> 密碼:<input type="password" name="password"/><br> 頭像1:<input type="file" name="headImg1"/><br> 頭像2:<input type="file" name="headImg2"/><br> <input type="submit" value="提交"/> </form> </body>
3. UploadServlet.java代碼
package com.gs.controller; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; import com.gs.domain.CFile; import com.gs.tools.FileUtil; @WebServlet("/UploadServlet") public class UploadServlet extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { Map<String, String> fieldMap = new HashMap(); Map<String,CFile> filesMap = new HashMap(); FileUtil.upload(request, fieldMap, filesMap); //拿數據 System.out.println(fieldMap); System.out.println(filesMap); } catch (Exception e) { request.setAttribute("message","類型不匹配"); request.getRequestDispatcher("register.jsp").forward(request, response); } } }
4. CFile.java代碼
package com.gs.domain; public class CFile { private String filename; private String filepath; public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } public String getFilepath() { return filepath; } public void setFilepath(String filepath) { this.filepath = filepath; } @Override public String toString() { return "CFile [filename=" + filename + ", filepath=" + filepath + "]"; } }
5. FileUtil.java 工具類代碼
package com.gs.tools; import java.io.File; import java.net.URLDecoder; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; import com.gs.domain.CFile; public class FileUtil { //準備只支持的圖片類型 private static final String[] IMG_TYPE = {"jpg","png","gif","bmp"}; public static void upload(HttpServletRequest request, Map<String,String> fieldMap, Map<String,CFile> filesMap) { //判斷是否有一個文件上傳的請求 boolean isMultipart = ServletFileUpload.isMultipartContent(request); if(isMultipart){ //爲基於磁盤的文件項創建工廠,並創建一個新的文件上傳對象 DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); upload.setFileSizeMax(1024*1024*2);//單個文件最大2M upload.setSizeMax(1024*1024*5); //所有文件的請求的大小 5M try { //拿到每一項表單控件組成的 FileItem類型的集合 List<FileItem> items = upload.parseRequest(request); for (FileItem fileItem : items) { System.out.println(fileItem); //如果是一般表單,用一般表單的處理方式 if(fileItem.isFormField()) { //表單控件name的名稱 String filedName = fileItem.getFieldName(); //表單控件name名稱對應的值 String value = fileItem.getString("UTF-8"); //value = new String(value.getBytes("ISO-8859-1"),"utf-8");//也可以解決亂碼問題 fieldMap.put(filedName, value);//將鍵值對添加到集合內 }else{//如果是文件上傳的控件 //獲取文件名,使用工具類:FilenameUtils解決ie瀏覽器拿文件全路徑名的問題 String name = FilenameUtils.getName(fileItem.getName()); //獲取後綴名 String ext = FilenameUtils.getExtension(name); //驗證後綴名是否滿足圖片類型 if(Arrays.asList(IMG_TYPE).contains(ext)) { String randomUUID = UUID.randomUUID().toString(); //(通過upload文件夾)獲取項目下的存儲資源的路徑 // F:\workspace\.metadata\...\文件上傳\\upload String path = request.getServletContext().getRealPath("/upload"); path = path.substring(0, path.indexOf(".metadata")); String pa = request.getContextPath(); //項目的上下文路徑,這裏獲取的是亂碼 pa = URLDecoder.decode(pa,"utf-8");//解碼 System.out.println(pa); path=path.replace('/', '\\')+pa+"\\WebContent\\upload"; System.out.println(path); //創建文件對象 File file = new File(path, randomUUID+"."+ext); //將二進制流寫入文件對象中 fileItem.write(file); CFile cfile = new CFile(); cfile.setFilename(randomUUID+"."+ext); cfile.setFilepath(file.getAbsolutePath()); filesMap.put(randomUUID+"."+ext,cfile); }else { throw new RuntimeException("文件類型不符合"); } } } }catch (RuntimeException e) { throw e; } catch (Exception e) { e.printStackTrace(); } } } }
2. 文件下載
文件下載可以有兩種方法:
1. 超連接直接下載功能
2. 使用java代碼經過servlet來進行下載
1. download.jsp代碼
<body> <p style="color:red"> 超連接直接下載功能 </p> <a href="download/俄羅斯方塊.html" download="俄羅斯方塊">俄羅斯方塊.html</a><br /> <a href="download/金玟岐 - 歲月神偷.mp3" download="歲月神偷">金玟岐 - 歲月神偷.mp3</a><br /> <a href="download/fun.mp4" download="fun視頻">fun.mp4</a><br /> <a href="download/2.jpg" download="二次元圖片">2.jpg</a><br /> <p style="color:red"> 使用java代碼經過servlet來進行下載 </p> <a href="DownloadServlet?filename=俄羅斯方塊.html">俄羅斯方塊.html</a><br /> <a href="DownloadServlet?filename=金玟岐 - 歲月神偷.mp3">金玟岐 - 歲月神偷.mp3</a><br /> <a href="DownloadServlet?filename=fun.mp4">fun.mp4</a><br /> <a href="DownloadServlet?filename=2.jpg">2.jpg</a><br /> </body>
2. DownloadServlet.java代碼
package com.gs.controller; import java.io.File; import java.io.IOException; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.file.Files; import java.nio.file.Paths; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/DownloadServlet") public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String pa = request.getContextPath(); //項目的上下文路徑,這裏獲取的是亂碼 pa = URLDecoder.decode(pa,"utf-8");//解碼 String filename = request.getParameter("filename"); String path = request.getServletContext().getRealPath("/download"); path = path.substring(0, path.indexOf(".metadata")); System.out.println(path); //F:\workspace\ path=path.replace('/', '\\')+pa+"\\WebContent\\download"; System.out.println(path); //F:\workspace\/文件上傳和下載\WebContent\download //將指定路徑的文件綁定成File對象 File file = new File(path,filename); //設置瀏覽器不能直接打開文件 response.setContentType("application/x-msdownload"); //解決瀏覽器下載文件沒有後綴名和文件名問題 String userAgent = request.getHeader("User-Agent"); if(userAgent.contains("MSIE")) { //IE瀏覽器 filename = URLEncoder.encode(filename,"UTF-8"); }else { //其他瀏覽器 filename = new String(filename.getBytes("UTF-8"),"ISO-8859-1"); } response.setHeader("Content-Disposition","attachment;filename="+filename); //將文件以流的形式輸出到頁面中下載 Files.copy(Paths.get(file.getAbsolutePath()), response.getOutputStream()); } }
頁面顯示: