使用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