大数据实训第二天

使用jsp/servlet简单实现文件上传与下载

使用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;  
    }  
}  
复制代码

  文件上传与下载就已经全部完成了。

原文地址:https://www.cnblogs.com/xiaohaigege666/p/11443757.html