最近學的東西有點雜,做了和看了寫什么就把它記錄下來。不得不說代碼真的很神奇,需要學習的還很多。
一直沒把文件上傳和下載搞清楚,今天就來動手寫一寫。
一 、依賴如下兩Jar實現的文件上傳。
實現代碼如下:
基礎實現:
1 package com.qq.upload; 2 3 import org.apache.commons.fileupload.FileItem; 4 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 5 import org.apache.commons.fileupload.servlet.ServletFileUpload; 6 7 import javax.servlet.ServletException; 8 import javax.servlet.annotation.WebServlet; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 import java.io.*; 13 import java.util.List; 14 @WebServlet("/doUpload") 15 public class Upload extends HttpServlet { 16 17 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 18 //得到上傳文件的保存目錄,將上傳的文件存放在WEB-INF目錄下面 不允許外界直接訪問,保證上傳文件的安全性 19 /* String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");*/ 20 String savePath = this.getServletContext().getRealPath("/LoadJsp"); 21 File file =new File(savePath); 22 if(!file.exists()&&!file.isDirectory()){ 23 System.out.println(savePath+"目標目錄不存在,需要進行創建"); 24 file.mkdir(); 25 26 } 27 String message = null; 28 try { 29 //1 創建DiskFileItemFactory工廠 30 DiskFileItemFactory factory = new DiskFileItemFactory(); 31 //2 創建一個文件上傳解析器 32 ServletFileUpload upload = new ServletFileUpload(factory); 33 //判斷提交上來的數據是不是表單上的數據 34 upload.setHeaderEncoding("UTF-8"); 35 if (!ServletFileUpload.isMultipartContent(req)) { 36 return; 37 } 38 39 //4 使用ServletFileUpload解析器來解析上傳數據,解析結果返回的是一個List<FileItem> 40 //集合,每一個FileItem對應一個Form表單的輸入項 41 List<FileItem> list = upload.parseRequest(req); 42 for(FileItem item:list) { 43 if (item.isFormField()) { 44 String name = item.getFieldName(); 45 String value = item.getString("UTF-8"); 46 System.out.println(name + "=" + value); 47 } else { 48 String filename = item.getName(); 49 System.out.println(filename); 50 if (filename == null || filename.trim().equals("")) { 51 continue; 52 } 53 //注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt 54 //處理獲取到的上傳文件的文件名的路徑部分,只保留文件名部分 55 filename = filename.substring(filename.lastIndexOf("\\") + 1); 56 //獲取item輸入流 57 InputStream inputStream = item.getInputStream(); 58 //創建一個文件輸出流 59 FileOutputStream fileOutputStream =new FileOutputStream(savePath+"\\"+filename); 60 //創建一個緩沖區 61 byte buffer[] = new byte[1024]; 62 //判斷輸入流是否已經讀完的標識 63 int len = 0; 64 while ((len=inputStream.read(buffer))>0) 65 { 66 fileOutputStream.write(buffer,0,len); 67 } 68 inputStream.close(); 69 fileOutputStream.close(); 70 item.delete(); 71 message = "文件上傳成功"; 72 73 74 75 } 76 } 77 }catch (Exception e) 78 { 79 message = "文件上傳失敗"; 80 e.printStackTrace(); 81 } 82 req.setAttribute("message",message); 83 req.getRequestDispatcher("/message.jsp").forward(req,resp); 84 } 85 86 @Override 87 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 88 doGet(req,resp); 89 } 90 }
改進實現:
package com.qq.upload; import org.apache.commons.fileupload.FileItem; 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.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.List; import java.util.UUID; /** 上述的代碼雖然可以成功將文件上傳到服務器上面的指定目錄當中,但是文件上傳功能有許多需要注意的小細節問題,以下列出的幾點需要特別注意的 1、為保證服務器安全,上傳文件應該放在外界無法直接訪問的目錄下,比如放於WEB-INF目錄下。 2、為防止文件覆蓋的現象發生,要為上傳文件產生一個唯一的文件名。 3、為防止一個目錄下面出現太多文件,要使用hash算法打散存儲。 4、要限制上傳文件的最大值。 5、要限制上傳文件的類型,在收到上傳文件名時,判斷后綴名是否合法。*/ @WebServlet("/doUpload2") public class Upload2 extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //得到上傳文件的保存目錄,將上傳的文件存放在WEB-INF目錄下面 不允許外界直接訪問,保證上傳文件的安全 String savePath = this.getServletContext().getRealPath("/LoadJsp"); String tempPath = this.getServletContext().getRealPath("/LoadJsp/temp"); File file =new File(tempPath); if(!file.exists()&&!file.isDirectory()){ System.out.println(tempPath+"目標目錄不存在,需要進行創建"); file.mkdir(); } String message = null; try { //1 創建DiskFileItemFactory工廠 DiskFileItemFactory factory = new DiskFileItemFactory(); //設置緩沖區得大小 factory.setSizeThreshold(1024*1000000); //設置上傳時生成得臨時文件保存目錄 factory.setRepository(file); //2 創建一個文件上傳解析器 ServletFileUpload upload = new ServletFileUpload(factory); //監聽文件上傳速度 upload.setProgressListener(new ProgressListener() { @Override public void update(long pBytesRead, long pContentLength, int arg2) { System.out.println("文件大小為:" + pContentLength+"當前處理"+pBytesRead); } }); //判斷提交上來的數據是不是表單上的數據 upload.setHeaderEncoding("UTF-8"); if (!ServletFileUpload.isMultipartContent(req)) { return; } //設置上傳文件總量得最大值 upload.setSizeMax(1024*10*1024000); //設置單個上傳文件得最大值 upload.setFileSizeMax(1024*1000000); //4 使用ServletFileUpload解析器來解析上傳數據,解析結果返回的是一個List<FileItem> //集合,每一個FileItem對應一個Form表單的輸入項 List<FileItem> list = upload.parseRequest(req); for(FileItem item:list) { if (item.isFormField()) { String name = item.getFieldName(); String value = item.getString("UTF-8"); System.out.println(name + "=" + value); } else { String filename = item.getName(); System.out.println(filename); if (filename == null || filename.trim().equals("")) { continue; } //注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt //處理獲取到的上傳文件的文件名的路徑部分,只保留文件名部分 filename = filename.substring(filename.lastIndexOf("\\") + 1); //獲得文件擴展名字 String fileExname = filename.substring(filename.lastIndexOf(".")+1); System.out.println("上傳的文件的擴展名是:"+fileExname); //獲取item輸入流 InputStream inputStream = item.getInputStream(); //得到保存文件得名稱 String saveFilename = makeFileName(filename); //得到文件得保存目錄 String realSavaPath = makePath(saveFilename,savePath); //創建一個文件輸出流 FileOutputStream fileOutputStream =new FileOutputStream(realSavaPath +"\\"+saveFilename); //創建一個緩沖區 byte buffer[] = new byte[1024]; //判斷輸入流是否已經讀完的標識 int len = 0; while ((len=inputStream.read(buffer))>0) { fileOutputStream.write(buffer,0,len); } inputStream.close(); fileOutputStream.close(); // item.delete(); message = "文件上傳成功"; } } }catch (Exception e) { message = "文件上傳失敗"; e.printStackTrace(); } req.setAttribute("message",message); req.getRequestDispatcher("/message.jsp").forward(req,resp); } /** * @method:makeFileName * 生成上傳文件的文件名,文件名以:UUID標識符+"_"+文件的原始名稱 * @param filename * @return */ private String makeFileName(String filename) { //為防止文件覆蓋的現象發生,要為上傳文件產生一個唯一的文件名 return UUID.randomUUID().toString()+"_"+filename; } /** * 為防止目錄下面出現太多文件,要使用hash算法打算存存儲 * @param filename * @param savePath * @return */ private String makePath(String filename,String savePath) { int hashcode = filename.hashCode(); int dir1 = hashcode&0xf;//0--15 /*int dir2 = (hashcode&0xf0)>>4;//0--15*/ //構建新的保存目錄 String dir = savePath+"\\"+dir1; //File可以代表文件也可以代表目錄 File file = new File(dir); if(!file.exists()) { file.mkdir(); System.out.println("創建新目錄成功!路徑地址為:"+dir); } return dir; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
列出WEB系統中所有下載文件:
package com.qq.upload; 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 java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * @BelongsPackage: com.qq.upload * @Author: ZHENGZHIQIANG * @CreateTime: 2019-03-18 11:16 * @Description: 列出WEB系統中所有下載文件 */ @WebServlet("/ListFileServlet") public class ListFileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //獲取上傳文件的目錄 String uploadFilePath = this.getServletContext().getRealPath("/LoadJsp"); //存儲要下載的文件名 Map<String, String> fileNameMap = new HashMap<>(); //遍歷filepath目錄下面的所有文件和目錄,將文件的文件名稱存儲到map中 listfile(new File(uploadFilePath), fileNameMap); //將Map集合發送到listfile.jsp頁面進行顯示 req.setAttribute("fileNameMap", fileNameMap); req.getRequestDispatcher("/listfile.jsp").forward(req, resp); } public void listfile(File file, Map<String, String> map) { if (!file.exists()) { File files[] = file.listFiles(); //遍歷files數組 for (File f : files) { listfile(f, map); } } else { /* 處理文件名,上傳后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分 file.getName().indexOf("_")檢索字符串中第一次出現"_"字符的位置,如果文件名類似於:9349249849-88343-8344_阿_凡_達.avi 那么file.getName().substring(file.getName().indexOf("_")+1)處理之后就可以得到阿_凡_達.avi部分 */ String realName = file.getName().substring(file.getName().indexOf("_") + 1); //file.getName()得到的是文件的原始名稱,這個名稱是唯一的,因此可以作為key,realName是處理過后的名稱,有可能會重復 map.put(file.getName(), realName); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
實現文件下載功能:
package com.qq.upload; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; /** * @Description: 實現文件下載功能 * @Author: ZHENGZHIQIANG * @CreateTime: 2019-03-21 10:43 */ public class DownLoadServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //得到要下載的文件名稱 String fileName = req.getParameter("filename"); fileName = new String(fileName.getBytes("iso8859-1"),"utf-8"); //上傳文件都是保存在/web-inf/loadjsp目錄下的子目錄中 String fileSaveRootPath = this.getServletContext().getRealPath("/LoadJsp"); //通過文件名找到文件所在的目錄 String path = findFileSavePathByFileName(fileName,fileSaveRootPath); //得到要下載的文件 File file = new File(path+"\\"+fileName); if(!file.exists()) { req.setAttribute("message","您要下載的資源不存在"); req.getRequestDispatcher("/message.jsp").forward(req,resp); return; } //處理文件名稱 String realName = fileName.substring(fileName.lastIndexOf("_")+1); //控制瀏覽器下載該文件 resp.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(realName,"UTF-8")); //讀取需要下載的文件 保存到文件輸入流 FileInputStream fileInputStream = new FileInputStream(path+"//"+fileName); //創建輸出流 OutputStream fileOutputStream = resp.getOutputStream(); //創建緩沖區 byte []buffer =new byte[1024]; int len =0; while ((len = fileInputStream.read(buffer))>0) { fileOutputStream.write(buffer,0,len); } fileInputStream.close(); fileOutputStream.close(); } public String findFileSavePathByFileName(String filename,String saveRootPath) { int hashcode = filename.hashCode(); int dir1 = hashcode&0xf; String dir = saveRootPath+"//"+dir1; File file = new File(dir); if(!file.exists()) { file.mkdir(); } return dir; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
效果如下:
JSP頁面代碼如下:
<%-- Created by IntelliJ IDEA. User: ZHENGZHIQIANG Date: 2019/3/11 Time: 11:36 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>File upload</title> </head> <body> <form action="/doUpload2" enctype="multipart/form-data" method="POST"> 上傳用戶:<input type="text" name="username"><br/> 上傳文件1:<input type="file" name="file1"><br/> 上傳文件2:<input type="file" name="file2"><br/> <input type="submit" value="提交"> </form> </body> </html> ************** <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%-- Created by IntelliJ IDEA. User: ZHENGZHIQIANG Date: 2019/3/18 Time: 11:52 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>下載文件顯示頁面</title> </head> <body> <%--遍歷Map集合--%> <c:forEach var="me" items="${fileNameMap}"> <c:url value="/ListFileServlet" var = "downurl"> <c:param name="filename" value="${me.key}"> </c:param> </c:url> ${me.value}<a href="${downurl}">下載</a> <br/> </c:forEach> </body> </html> ******************** <%-- Created by IntelliJ IDEA. User: ZHENGZHIQIANG Date: 2019/3/13 Time: 16:28 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Return message</title> </head> <body> ${message} </body> </html>