使用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>
- 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);
- }
- }
- <%@ 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;
- }
- }
文件上传与下载就已经全部完成了。