JavaWeb实现文件下载
1. 编写文件上传Servlet
1 public class FileUpload1 extends HttpServlet { 2 @Override 3 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 4 5 InputStream in = null; 6 OutputStream out = null; 7 8 // 获取上传文件目录 9 String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); 10 11 try { 12 // 使用默认配置创建解析器工厂 13 DiskFileItemFactory factory = new DiskFileItemFactory(); 14 // 获取解析器 15 ServletFileUpload upload = new ServletFileUpload(factory); 16 upload.setProgressListener(new ProgressListener() { 17 @Override 18 public void update(long l, long l1, int i) { 19 System.out.println("文件大小为:" + l1 + ",当前已处理:" + l); 20 } 21 }); 22 // 解决上传文件名的中文乱码问题 23 upload.setHeaderEncoding("UTF-8"); 24 // 上传表单是否为multipart/form-data类型 25 if (!upload.isMultipartContent(request)) { 26 return; 27 } 28 // 解析request的输入流 29 List<FileItem> fileItemList = upload.parseRequest(request); 30 // 迭代list集合 31 for (FileItem fileItem : fileItemList) { 32 if (fileItem.isFormField()) { 33 // 普通字段 34 String name = fileItem.getFieldName(); 35 // 调用getString重载方法, 解决上传数据的中文乱码问题 36 String value = fileItem.getString("UTF-8"); 37 System.out.println(name + "=" + value); 38 } else { 39 // 上传文件 40 // 获取上传文件名 41 String fileName = fileItem.getName(); 42 // input:file没有指定上传文件时, 结束本次循环并继续下一次循环 43 if(fileName == null && fileName.trim().equals("")) { 44 continue; 45 } 46 fileName = fileName.substring(fileName.lastIndexOf("\\")+1); 47 // 使用UUID作为上传文件的名称 48 fileName = makeFileName(fileName); 49 // 获取输入流 50 in = fileItem.getInputStream(); 51 52 // 上传文件名若不存在, 则先创建 53 File savePathDir = new File(savePath); 54 if (!savePathDir.exists()) { 55 savePathDir.mkdir(); 56 } 57 58 // 使用hash算法产生当前上传图片的随机目录 59 String currentFileSavePath = makePath(savePath, fileName); 60 61 // 获取输出流 62 out = new FileOutputStream(currentFileSavePath + "\\" + fileName); 63 int len = 0; 64 byte[] buffer = new byte[1024]; 65 while((len=in.read(buffer)) > 0) { 66 out.write(buffer, 0, len); 67 } 68 } 69 } 70 } catch (Exception e) { 71 e.printStackTrace(); 72 } finally { 73 if (in != null) { 74 in.close(); 75 } 76 if (out != null) { 77 out.close(); 78 } 79 } 80 81 } 82 public String makeFileName(String fileName) { 83 return UUID.randomUUID().toString() + "_" + fileName; 84 } 85 public String makePath(String savePath, String fileName) { 86 // 根据文件名产生int型hashcode, 32位二进制 87 int hashcode = fileName.hashCode(); 88 // 获取第4位 0-15 89 int dir1 = hashcode&0xf; 90 // 获取第5-8位 0-15 91 int dir2 = (hashcode&0xf0)>>4; 92 // 凭借随机目录 93 String dir = savePath + "\\" + dir1 + "\\" + dir2; // upload\2\4 94 // 若目录不存在时, 创建目录 95 File file = new File(dir); 96 if(!file.exists()) { 97 file.mkdirs(); 98 } 99 return dir; 100 } 101 102 @Override 103 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 104 doGet(req, resp); 105 } 106 }
2. 编写获取所有下载文件名称Servlet
1 /** 2 * Created by IntelliJ IDEA. 3 * 4 * @Auther: ShaoHsiung 5 * @Date: 2018/8/26 16:26 6 * @Title: 7 * @Description: 列出网站所有下载文件 8 */ 9 public class ListFileServlet extends HttpServlet { 10 @Override 11 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 12 13 // 获取下载目录路径 14 String filePath = this.getServletContext().getRealPath("/WEB-INF/upload"); 15 // 创建存储文件下载路径的Map集合 16 Map filePathMap = new HashMap(); 17 // 将下载目录中所有文件名称存储到Map集合中 18 listFile(new File(filePath), filePathMap); 19 // 存储数据后跳转 20 request.setAttribute("map", filePathMap); 21 request.getRequestDispatcher("/listfile.jsp").forward(request, response); 22 } 23 24 /** 25 * 将下载目录中所有文件名称存储到Map集合中 26 * @param file 下载目录 27 * @param filePathMap Map集合 28 */ 29 private void listFile(File file, Map filePathMap) { 30 if(!file.isFile()) { 31 // 文件为目录时 32 File[] files = file.listFiles(); 33 for (File f : files) { 34 // 递归调用 35 listFile(f, filePathMap); 36 } 37 } else { 38 // 9349249849-88343-8344_阿_凡_达.avi 处理结果为: 阿_凡_达.avi 39 String realName = file.getName().substring(file.getName().indexOf("_")+1); 40 // 9349249849-88343-8344_阿_凡_达.avi -> 阿_凡_达.avi 41 filePathMap.put(file.getName(), realName); 42 } 43 } 44 45 @Override 46 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 47 doGet(req, resp); 48 } 49 }
3. 处理文件下载请求Servlet
1 public class FileDownload extends HttpServlet { 2 @Override 3 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 4 5 // 获取下载文件名称的key 6 String filename = request.getParameter("filename"); //23239283-92489-dfsd_阿凡达.avi 7 // 解决get请求的中文乱码问题 8 filename = new String(filename.getBytes("iso8859-1"),"UTF-8"); 9 // 获取下载目录 10 String path = makePath(filename,this.getServletContext().getRealPath("/WEB-INF/upload")); 11 // 获取下载文件 12 File file = new File(path + "\\" + filename); 13 // 下载文件不存在时 14 if(!file.exists()){ 15 request.setAttribute("message", "您要下载的资源已被删除!!"); 16 request.getRequestDispatcher("/message.jsp").forward(request, response); 17 return; 18 } 19 // 获取下载文件名称 阿凡达.avi 20 String realname = filename.substring(filename.indexOf("_") + 1); 21 // 通知浏览器以下载方式打开, 不同浏览器可能不同 22 response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8")); 23 // 下载文件 24 FileInputStream in = new FileInputStream(path + "\\" + filename); 25 OutputStream out = response.getOutputStream(); 26 byte buffer[] = new byte[1024]; 27 int len = 0; 28 while((len=in.read(buffer))>0){ 29 out.write(buffer, 0, len); 30 } 31 in.close(); 32 out.close(); 33 34 } 35 36 /** 37 * 根据文件名称产生随机目录并将下载路径与随机目录拼接 38 * @param filename 文件名称 39 * @param savePath 下载路径 40 * @return 下载路径与随机目录拼接结果 41 */ 42 private String makePath(String filename,String savePath){ 43 44 int hashcode = filename.hashCode(); 45 int dir1 = hashcode&0xf; //0--15 46 int dir2 = (hashcode&0xf0)>>4; //0-15 47 48 String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5 49 File file = new File(dir); 50 if(!file.exists()){ 51 file.mkdirs(); 52 } 53 return dir; 54 } 55 56 @Override 57 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 58 doGet(req, resp); 59 } 60 }
4. 配置web.xml
1 <!-- 文件上传 --> 2 <servlet> 3 <servlet-name>FileUpload1</servlet-name> 4 <servlet-class>fileupload.FileUpload1</servlet-class> 5 </servlet> 6 <servlet-mapping> 7 <servlet-name>FileUpload1</servlet-name> 8 <url-pattern>/servlet/FileUpload1</url-pattern> 9 </servlet-mapping> 10 11 <!--文件下载--> 12 <servlet> 13 <servlet-name>ListFileServlet</servlet-name> 14 <servlet-class>fileupload.ListFileServlet</servlet-class> 15 </servlet> 16 <servlet-mapping> 17 <servlet-name>ListFileServlet</servlet-name> 18 <url-pattern>/servlet/ListFileServlet</url-pattern> 19 </servlet-mapping> 20 <servlet> 21 <servlet-name>FileDownload</servlet-name> 22 <servlet-class>fileupload.FileDownload</servlet-class> 23 </servlet> 24 <servlet-mapping> 25 <servlet-name>FileDownload</servlet-name> 26 <url-pattern>/servlet/FileDownload</url-pattern> 27 </servlet-mapping>
5. 编写获取文件名称JSP
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 3 4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 5 <html> 6 <head> 7 <title>My JSP 'listfile.jsp' starting page</title> 8 </head> 9 10 <body> 11 12 <c:forEach var="me" items="${map}"> 13 <c:url value="/servlet/FileDownload" var="downurl"> 14 <c:param name="filename" value="${me.key}"></c:param> 15 </c:url> 16 ${me.value } <a href="${downurl}">下载</a> <br/> 17 </c:forEach> 18 19 </body> 20 </html>
注意:
URL地址栏 -> 非ASCII码字符 -> URL编码
使用c:url传递中文数据
6. 编写文件上传JSP
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <html> 3 <head> 4 <title>演示文件上传</title> 5 </head> 6 <body> 7 <form action="${pageContext.request.contextPath}/servlet/FileUpload1" method="post" enctype="multipart/form-data"> 8 用户名: <input type="text" name="username"/><br/> 9 文件1: <input type="file" name="file1"/><br/> 10 文件2: <input type="file" name="file1"/><br/> 11 <input type="submit"/> 12 </form> 13 </body> 14 </html>
7. 效果演示
在浏览器中访问http://localhost:8080/servlet/ListFileServlet