• JavaWeb(六) IO流实现文件上传下载


        最近学的东西有点杂,做了和看了写什么就把它记录下来。不得不说代码真的很神奇,需要学习的还很多。

    一直没把文件上传和下载搞清楚,今天就来动手写一写。

    一 、依赖如下两Jar实现的文件上传。

    实现代码如下:

        基础实现:

     1 package com.qq.upload;
     2 
     3 import org.apache.commons.fileupload.FileItem;
     4 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
     5 import org.apache.commons.fileupload.servlet.ServletFileUpload;
     6 
     7 import javax.servlet.ServletException;
     8 import javax.servlet.annotation.WebServlet;
     9 import javax.servlet.http.HttpServlet;
    10 import javax.servlet.http.HttpServletRequest;
    11 import javax.servlet.http.HttpServletResponse;
    12 import java.io.*;
    13 import java.util.List;
    14 @WebServlet("/doUpload")
    15 public class Upload  extends HttpServlet {
    16 
    17     public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    18         //得到上传文件的保存目录,将上传的文件存放在WEB-INF目录下面 不允许外界直接访问,保证上传文件的安全性
    19 /*        String savePath  = this.getServletContext().getRealPath("/WEB-INF/upload");*/
    20         String savePath = this.getServletContext().getRealPath("/LoadJsp");
    21         File file  =new File(savePath);
    22         if(!file.exists()&&!file.isDirectory()){
    23             System.out.println(savePath+"目标目录不存在,需要进行创建");
    24             file.mkdir();
    25 
    26         }
    27         String message = null;
    28         try {
    29             //1 创建DiskFileItemFactory工厂
    30             DiskFileItemFactory factory = new DiskFileItemFactory();
    31             //2 创建一个文件上传解析器
    32             ServletFileUpload upload = new ServletFileUpload(factory);
    33             //判断提交上来的数据是不是表单上的数据
    34             upload.setHeaderEncoding("UTF-8");
    35             if (!ServletFileUpload.isMultipartContent(req)) {
    36                 return;
    37             }
    38 
    39             //4 使用ServletFileUpload解析器来解析上传数据,解析结果返回的是一个List<FileItem>
    40             //集合,每一个FileItem对应一个Form表单的输入项
    41             List<FileItem> list = upload.parseRequest(req);
    42             for(FileItem item:list) {
    43                 if (item.isFormField()) {
    44                     String name = item.getFieldName();
    45                     String value = item.getString("UTF-8");
    46                     System.out.println(name + "=" + value);
    47                 } else {
    48                     String filename = item.getName();
    49                     System.out.println(filename);
    50                     if (filename == null || filename.trim().equals("")) {
    51                         continue;
    52                     }
    53                     //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:a1.txt,而有些只是单纯的文件名,如:1.txt
    54                     //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
    55                     filename = filename.substring(filename.lastIndexOf("\") + 1);
    56                     //获取item输入流
    57                     InputStream inputStream = item.getInputStream();
    58                     //创建一个文件输出流
    59                     FileOutputStream fileOutputStream  =new FileOutputStream(savePath+"\"+filename);
    60                     //创建一个缓冲区
    61                     byte buffer[] = new byte[1024];
    62                     //判断输入流是否已经读完的标识
    63                     int len = 0;
    64                     while ((len=inputStream.read(buffer))>0)
    65                     {
    66                         fileOutputStream.write(buffer,0,len);
    67                     }
    68                     inputStream.close();
    69                     fileOutputStream.close();
    70                     item.delete();
    71                     message = "文件上传成功";
    72 
    73 
    74 
    75                 }
    76             }
    77         }catch (Exception e)
    78         {
    79             message = "文件上传失败";
    80             e.printStackTrace();
    81         }
    82         req.setAttribute("message",message);
    83         req.getRequestDispatcher("/message.jsp").forward(req,resp);
    84     }
    85 
    86     @Override
    87     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    88         doGet(req,resp);
    89     }
    90 }

        改进实现:

    package com.qq.upload;
    
    
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.ProgressListener;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.util.List;
    import java.util.UUID;
    
    /**         上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的
              1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
              2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
              3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
              4、要限制上传文件的最大值。
              5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。*/
    @WebServlet("/doUpload2")
    public class Upload2  extends HttpServlet {
    
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //得到上传文件的保存目录,将上传的文件存放在WEB-INF目录下面 不允许外界直接访问,保证上传文件的安全
            String savePath = this.getServletContext().getRealPath("/LoadJsp");
            String tempPath = this.getServletContext().getRealPath("/LoadJsp/temp");
            File file  =new File(tempPath);
            if(!file.exists()&&!file.isDirectory()){
                System.out.println(tempPath+"目标目录不存在,需要进行创建");
                file.mkdir();
    
            }
            String message = null;
            try {
                //1 创建DiskFileItemFactory工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                //设置缓冲区得大小
                factory.setSizeThreshold(1024*1000000);
                //设置上传时生成得临时文件保存目录
                factory.setRepository(file);
                //2 创建一个文件上传解析器
                ServletFileUpload upload = new ServletFileUpload(factory);
                //监听文件上传速度
                upload.setProgressListener(new ProgressListener() {
                    @Override
                    public void update(long pBytesRead, long pContentLength, int arg2) {
                        System.out.println("文件大小为:" + pContentLength+"当前处理"+pBytesRead);
                    }
                });
                //判断提交上来的数据是不是表单上的数据
                upload.setHeaderEncoding("UTF-8");
                if (!ServletFileUpload.isMultipartContent(req)) {
                    return;
                }
                //设置上传文件总量得最大值
                upload.setSizeMax(1024*10*1024000);
                //设置单个上传文件得最大值
                upload.setFileSizeMax(1024*1000000);
    
                //4 使用ServletFileUpload解析器来解析上传数据,解析结果返回的是一个List<FileItem>
                //集合,每一个FileItem对应一个Form表单的输入项
                List<FileItem> list = upload.parseRequest(req);
                for(FileItem item:list) {
                    if (item.isFormField()) {
                        String name = item.getFieldName();
                        String value = item.getString("UTF-8");
                        System.out.println(name + "=" + value);
                    } else {
                        String filename = item.getName();
                        System.out.println(filename);
                        if (filename == null || filename.trim().equals("")) {
                            continue;
                        }
                        //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:a1.txt,而有些只是单纯的文件名,如:1.txt
                        //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                        filename = filename.substring(filename.lastIndexOf("\") + 1);
                        //获得文件扩展名字
                    String    fileExname = filename.substring(filename.lastIndexOf(".")+1);
                        System.out.println("上传的文件的扩展名是:"+fileExname);
                        //获取item输入流
                        InputStream inputStream = item.getInputStream();
                        //得到保存文件得名称
                        String saveFilename  = makeFileName(filename);
                        //得到文件得保存目录
                        String realSavaPath = makePath(saveFilename,savePath);
                        //创建一个文件输出流
    
                        FileOutputStream fileOutputStream  =new FileOutputStream(realSavaPath
                                +"\"+saveFilename);
                        //创建一个缓冲区
                        byte buffer[] = new byte[1024];
                        //判断输入流是否已经读完的标识
                        int len = 0;
                        while ((len=inputStream.read(buffer))>0)
                        {
                            fileOutputStream.write(buffer,0,len);
                        }
                        inputStream.close();
                        fileOutputStream.close();
                       // item.delete();
                        message = "文件上传成功";
    
    
    
                    }
                }
            }catch (Exception e)
            {
                message = "文件上传失败";
                e.printStackTrace();
            }
            req.setAttribute("message",message);
            req.getRequestDispatcher("/message.jsp").forward(req,resp);
        }
    
        /**
         * @method:makeFileName
         * 生成上传文件的文件名,文件名以:UUID标识符+"_"+文件的原始名称
         * @param filename
         * @return
         */
        private String makeFileName(String filename)
        {
            //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
            return UUID.randomUUID().toString()+"_"+filename;
        }
    
        /**
         * 为防止目录下面出现太多文件,要使用hash算法打算存存储
         * @param filename
         * @param savePath
         * @return
         */
        private String makePath(String filename,String savePath)
        {
    
            int hashcode = filename.hashCode();
            int dir1 = hashcode&0xf;//0--15
            /*int dir2 = (hashcode&0xf0)>>4;//0--15*/
    
            //构建新的保存目录
            String dir   = savePath+"\"+dir1;
            //File可以代表文件也可以代表目录
            File file = new File(dir);
            if(!file.exists())
            {
                file.mkdir();
                System.out.println("创建新目录成功!路径地址为:"+dir);
    
            }
            return  dir;
    
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    }
    列出WEB系统中所有下载文件:
    package com.qq.upload;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @BelongsPackage: com.qq.upload
     * @Author: ZHENGZHIQIANG
     * @CreateTime: 2019-03-18 11:16
     * @Description: 列出WEB系统中所有下载文件
     */
    @WebServlet("/ListFileServlet")
    public class ListFileServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取上传文件的目录
            String uploadFilePath = this.getServletContext().getRealPath("/LoadJsp");
            //存储要下载的文件名
            Map<String, String> fileNameMap = new HashMap<>();
            //遍历filepath目录下面的所有文件和目录,将文件的文件名称存储到map中
            listfile(new File(uploadFilePath), fileNameMap);
            //将Map集合发送到listfile.jsp页面进行显示
            req.setAttribute("fileNameMap", fileNameMap);
            req.getRequestDispatcher("/listfile.jsp").forward(req, resp);
        }
    
        public void listfile(File file, Map<String, String> map) {
            if (!file.exists()) {
                File files[] = file.listFiles();
                //遍历files数组
                for (File f : files) {
                    listfile(f, map);
                }
            } else {
                /*
                 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
                 file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
                 那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分
                 */
                String realName = file.getName().substring(file.getName().indexOf("_") + 1);
                //file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
                map.put(file.getName(), realName);
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    
    实现文件下载功能:
    package com.qq.upload;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.net.URLEncoder;
    
    /**
     * @Description: 实现文件下载功能
     * @Author: ZHENGZHIQIANG
     * @CreateTime: 2019-03-21 10:43
     */
    public class DownLoadServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //得到要下载的文件名称
            String fileName =  req.getParameter("filename");
            fileName = new String(fileName.getBytes("iso8859-1"),"utf-8");
            //上传文件都是保存在/web-inf/loadjsp目录下的子目录中
            String fileSaveRootPath = this.getServletContext().getRealPath("/LoadJsp");
            //通过文件名找到文件所在的目录
            String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
            //得到要下载的文件
            File file = new File(path+"\"+fileName);
            if(!file.exists())
            {
                req.setAttribute("message","您要下载的资源不存在");
                req.getRequestDispatcher("/message.jsp").forward(req,resp);
                return;
            }
            //处理文件名称
            String realName = fileName.substring(fileName.lastIndexOf("_")+1);
            //控制浏览器下载该文件
            resp.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(realName,"UTF-8"));
            //读取需要下载的文件 保存到文件输入流
            FileInputStream fileInputStream = new FileInputStream(path+"//"+fileName);
            //创建输出流
            OutputStream fileOutputStream = resp.getOutputStream();
            //创建缓冲区
            byte []buffer =new byte[1024];
            int len =0;
            while ((len = fileInputStream.read(buffer))>0)
            {
                fileOutputStream.write(buffer,0,len);
            }
            fileInputStream.close();
            fileOutputStream.close();
        }
            public String findFileSavePathByFileName(String filename,String saveRootPath)
            {
                int hashcode = filename.hashCode();
                int dir1 = hashcode&0xf;
                String dir  = saveRootPath+"//"+dir1;
                File file = new File(dir);
                if(!file.exists())
                {
                    file.mkdir();
                }
                return dir;
            }
    
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
     

    效果如下:

    JSP页面代码如下:

    <%--
      Created by IntelliJ IDEA.
      User: ZHENGZHIQIANG
      Date: 2019/3/11
      Time: 11:36
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>File upload</title>
      </head>
      <body>
    <form action="/doUpload2" enctype="multipart/form-data" method="POST">
             上传用户:<input type="text" name="username"><br/>
             上传文件1:<input type="file" name="file1"><br/>
             上传文件2:<input type="file" name="file2"><br/>
             <input type="submit" value="提交">
    </form>
      </body>
    </html>
    
    **************
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--
      Created by IntelliJ IDEA.
      User: ZHENGZHIQIANG
      Date: 2019/3/18
      Time: 11:52
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>下载文件显示页面</title>
    </head>
    <body>
    <%--遍历Map集合--%>
    <c:forEach var="me" items="${fileNameMap}">
    <c:url value="/ListFileServlet" var = "downurl">
        <c:param name="filename" value="${me.key}">
        </c:param>
    </c:url>
        ${me.value}<a href="${downurl}">下载</a>
        <br/>
    </c:forEach>
    
    </body>
    </html>
    ********************
    <%--
      Created by IntelliJ IDEA.
      User: ZHENGZHIQIANG
      Date: 2019/3/13
      Time: 16:28
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Return message</title>
    </head>
    <body>
    ${message}
    </body>
    </html>
  • 相关阅读:
    Arduino nano的bootloader文件烧录
    arduino通信问题的学习与解决
    arduino中的serial .available()和serial.read()
    arduino 通过串口接收string,int类型数据
    Arduino读取串口数据并进行字符串分割
    Arduino 的读串口与写串口
    代理模式
    策略模式
    python中的深拷贝
    Python中的三个特殊函数
  • 原文地址:https://www.cnblogs.com/zqoceean/p/10583262.html
Copyright © 2020-2023  润新知