使用JSP/Servlet簡單實現文件上傳與下載
通過學習黑馬jsp教學視頻,我學會了使用jsp與servlet簡單地實現web的文件的上傳與下載,首先感謝黑馬。好了,下面來簡單了解如何通過使用jsp與servlet實現文件上傳與下載。
在寫代碼之前,我們需要導入兩個額外的jar包,一個是common-io-2.2.jar,另一個是commons-fileupload-1.3.1.jar,將這個兩個jar 包導入WEB-INF/lib目錄里。
首先,想要在web端即網頁上實現文件上傳,必須要提供一個選擇文件的框,即設置一個<input type="file"/>的元素,光有這個還不行,還需要對<input>元素外的表單form進行設置,將form的enctype屬性設置為“multipart/form-data”,即<form action="" method="post" enctype="multipart/form-data">,當然請求方式也必須是post。讓我們來簡單做一個上傳的jsp頁面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>文件上傳</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="${pageContext.request.contextPath}/servlet/UploadServlet" method="post" enctype="multipart/form-data"> name:<input name="name"/><br/> file1:<input type="file" name="f1"/><br/> <input type="submit" value="上傳"> </form> </body> </html>
jsp頁面做好之后,我們就要寫一個UploadServlet,在編寫上傳servlet時,我們需要考慮到如果上傳的文件出現重名的情況,以及上傳的文件可能會出現的亂碼情況,所以我們需要編碼與客戶端一致,並且根據文件名的hashcode計算存儲目錄,避免一個文件夾中的文件過多,當然為了保證服務器的安全,我們將存放文件的目錄放在用戶直接訪問不到的地方,比如在WEB-INF文件夾下創建一個file文件夾。具體做法如下:
public class UploadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); System.out.print(request.getRemoteAddr()); boolean isMultipart = ServletFileUpload.isMultipartContent(request); if(!isMultipart){ throw new RuntimeException("請檢查您的表單的enctype屬性,確定是multipart/form-data"); } DiskFileItemFactory dfif = new DiskFileItemFactory(); ServletFileUpload parser = new ServletFileUpload(dfif); parser.setFileSizeMax(3*1024*1024);//設置單個文件上傳的大小 parser.setSizeMax(6*1024*1024);//多文件上傳時總大小限制 List<FileItem> items = null; try { items = parser.parseRequest(request); }catch(FileUploadBase.FileSizeLimitExceededException e) { out.write("上傳文件超出了3M"); return; }catch(FileUploadBase.SizeLimitExceededException e){ out.write("總文件超出了6M"); return; }catch (FileUploadException e) { e.printStackTrace(); throw new RuntimeException("解析上傳內容失敗,請重新試一下"); } //處理請求內容 if(items!=null){ for(FileItem item:items){ if(item.isFormField()){ processFormField(item); }else{ processUploadField(item); } } } out.write("上傳成功!"); } private void processUploadField(FileItem item) { try { String fileName = item.getName(); //用戶沒有選擇上傳文件時 if(fileName!=null&&!fileName.equals("")){ fileName = UUID.randomUUID().toString()+"_"+FilenameUtils.getName(fileName); //擴展名 String extension = FilenameUtils.getExtension(fileName); //MIME類型 String contentType = item.getContentType(); //分目錄存儲:日期解決 // Date now = new Date(); // DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // // String childDirectory = df.format(now); //按照文件名的hashCode計算存儲目錄 String childDirectory = makeChildDirectory(getServletContext().getRealPath("/WEB-INF/files/"),fileName); String storeDirectoryPath = getServletContext().getRealPath("/WEB-INF/files/"+childDirectory); File storeDirectory = new File(storeDirectoryPath); if(!storeDirectory.exists()){ storeDirectory.mkdirs(); } System.out.println(fileName); item.write(new File(storeDirectoryPath+File.separator+fileName));//刪除臨時文件 } } catch (Exception e) { throw new RuntimeException("上傳失敗,請重試"); } } //計算存放的子目錄 private String makeChildDirectory(String realPath, String fileName) { int hashCode = fileName.hashCode(); int dir1 = hashCode&0xf;// 取1~4位 int dir2 = (hashCode&0xf0)>>4;//取5~8位 String directory = ""+dir1+File.separator+dir2; File file = new File(realPath,directory); if(!file.exists()) file.mkdirs(); return directory; } private void processFormField(FileItem item) { String fieldName = item.getFieldName();//字段名 String fieldValue; try { fieldValue = item.getString("UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("不支持UTF-8編碼"); } System.out.println(fieldName+"="+fieldValue); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
至此,上傳的任務就基本完成了,有了上傳當然也要有下載功能,在下載之前,我們需要將所有已經上傳的文件顯示在網頁上,通過一個servlet與一個jsp頁面來顯示,servlet代碼如下:
public class ShowAllFilesServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String storeDirectory = getServletContext().getRealPath("/WEB-INF/files"); File root = new File(storeDirectory); //用Map保存遞歸的文件名:key:UUID文件名 value:老文件名 Map<String, String> map = new HashMap<String, String>(); treeWalk(root,map); request.setAttribute("map", map); request.getRequestDispatcher("/listFiles.jsp").forward(request, response); } //遞歸,把文件名放到Map中 private void treeWalk(File root, Map<String, String> map) { if(root.isFile()){ String fileName = root.getName();//文件名 String oldFileName = fileName.substring(fileName.indexOf("_")+1); map.put(fileName, oldFileName); }else{ File fs[] = root.listFiles(); for(File file:fs){ treeWalk(file, map); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
通過上面的servlet轉發到listFiles.jsp頁面,listFiles.jsp頁面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>title</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h1>以下資源可供下載</h1> <c:forEach items="${map}" var="me"> <c:url value="/servlet/DownloadServlet" var="url"> <c:param name="filename" value="${me.key}"></c:param> </c:url> ${me.value} <a href="${url}">下載</a><br/> </c:forEach> </body> </html>
到這里,文件也顯示出來了,就需要點擊下載進行下載文件了,最后一步,我們再編寫一個DownloadServlet:
public class DownloadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String uuidfilename = request.getParameter("filename");//get方式提交的 uuidfilename = new String(uuidfilename.getBytes("ISO-8859-1"),"UTF-8");//UUID的文件名 String storeDirectory = getServletContext().getRealPath("/WEB-INF/files"); //得到存放的子目錄 String childDirecotry = makeChildDirectory(storeDirectory, uuidfilename); //構建輸入流 InputStream in = new FileInputStream(storeDirectory+File.separator+childDirecotry+File.separator+uuidfilename); //下載 String oldfilename = uuidfilename.substring(uuidfilename.indexOf("_")+1); //通知客戶端以下載的方式打開 response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(oldfilename, "UTF-8")); OutputStream out = response.getOutputStream(); int len = -1; byte b[] = new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } //計算存放的子目錄 private String makeChildDirectory(String realPath, String fileName) { int hashCode = fileName.hashCode(); int dir1 = hashCode&0xf;// 取1~4位 int dir2 = (hashCode&0xf0)>>4;//取5~8位 String directory = ""+dir1+File.separator+dir2; File file = new File(realPath,directory); if(!file.exists()) file.mkdirs(); return directory; } }
文件上傳與下載就已經全部完成了。
本文來源於 http://blog.csdn.net/wetsion/article/details/50890031