zoukankan      html  css  js  c++  java
  • Java Web(十一) 文件上传与下载

    文件上传

    上传的准备工作

    • 表单method必须为post
    • 提供file组件
    • 设置form标签的enctype属性为multipart/form-data,如果没有设置enctype属性,浏览器是无法将文件自身传递到服务端的(enctype默认为application/x-www-form-urlencoded)
    <form action="fileupload.do" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username"/><br/>
        密码:<input type="password" name="password"/><br/>
        上传文件:<input name="file" type="file" /><br/>
        <input type="submit"/>
    </form>
    

    上传时HTTP协议的格式

    1. enctype为application/x-www-form-urlencoded时

      从表单发送数据到服务器,数据是以键值对的形式存放在请求体中发送到服务器的。

      使用google浏览器的自动抓包(F12),可以查看表单数据在HTTP协议中的格式:

      img

      request.getParameter(name)是以键值对的形式获取值的,所以可以通过该方法得到表单中的数据。可以得到文件名,但是得不到文件!

    2. enctype为multipart/form-data时

      在上传时,multipart/form-data请求会把表单的数据处理为一条消息,以标签为单元,用分隔符(boundary)分开。既可以上传普通表单数据,也可以上传文件。content-disposition,用来说明字段的一些信息。当上传的字段是文件时,会有Content-Type来表明文件类型。

      使用google浏览器查看上传时表单数据在HTTP协议的格式:

      img

      表单数据在HTTP协议中不是以键值对形式存在的,所以在服务器端是无法通过request.getParameter(name)获取数据的。

      可以利用分隔符boundary和Content-type属性自己编写代码实现文件上传。

    3. 在服务器端查看从客户端传来的表单数据

      可以使用request.getInputStream()来获取从客户端传来的数据,可以通过下面的代码把传来的数据输出到控制台:

        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              InputStream is = request.getInputStream();
              int i = is.read();
              while(i != -1) {
                  char c = (char)i;
                  System.out.print(c);
                  i = is.read();
              }
          }
      

      在没有设置enctype属性时,传到服务器的数据为:

      img

      文件上传时,传到服务器的数据为:

      img

      其中的乱码为二进制数据,也就是要上传的文件。

    FileUpload实现文件上传

    FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下面的文件上传功能。

    使用FileUpload需要两个jar包的支持,这里FileUpload版本为:commons- fileupload-1.2.1,Commons IO版本为:commons-io-1.4。

    客户端代码:

    <body>
    <form action="fileupload.do" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username"/><br/>
        密码:<input type="password" name="password"/><br/>
        上传文件:<input name="file" type="file" /><br/>
        <input type="submit"/>
    </form>
    </body>
    

    服务器端代码为:

    @WebServlet(name = "FileServlet",urlPatterns = "/fileupload.do")
    public class FileServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
    
            //判断是否支持文件上传
            boolean isMultipart  = ServletFileUpload.isMultipartContent(request);
            if(!isMultipart) {
                throw new RuntimeException("不支持文件上传");
            }
            //创建一个磁盘工厂
            DiskFileItemFactory  factory=new DiskFileItemFactory();
            //配置缓存库
            ServletContext servletContext = this.getServletConfig().getServletContext();
            File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
            factory.setRepository(repository);
            //解析数据
            ServletFileUpload fileUpload=new ServletFileUpload(factory);
            List<FileItem> items = null;
            try {
                items=fileUpload.parseRequest(request);
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
    
            for(FileItem item : items) {
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString();
                    System.out.println(name + " " + value);
                } else {
                    //取文件名
                    String fileName = item.getName();
                    fileName = fileName.substring(fileName.lastIndexOf("\") + 1);
                    //取文件拓展名
                    String exten = fileName.substring(fileName.lastIndexOf("."));
                    //新文件名,防止文件重名
                    String newFileName = UUID.randomUUID().toString().replace("-", "") + exten;
                    //把文件写入到upload文件夹下
                    String path = this.getServletConfig().getServletContext().getRealPath("/");
                    String directPath = path + "upload\" + newFileName;
                    File file = new File(directPath);
                    OutputStream os = new FileOutputStream(file);
                    InputStream is = item.getInputStream();
                    byte[] b = new byte[1024];
                    int len = 0;
                    while ((len = is.read(b)) != -1) {
                        os.write(b, 0, len);
                    }
                    os.close();
                    is.close();
                }
            }
            request.getRequestDispatcher("ok.jsp").forward(request, response);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    

    文件下载

    @WebServlet(name = "DownloadServlet", urlPatterns = "/download.do")
    public class DownloadServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获得要下载的文件的名称
            String filename = request.getParameter("filename");
            // 告诉客户端该文件不是直接解析,而是以附件形式打开(下载)
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            // 获取文件的绝对路径
            String path = this.getServletContext().getRealPath("download/" + filename);
            // 获得该文件的输入流
            InputStream in = new FileInputStream(path);
            // 获得输出流--通过response获得的输出流 用于向客户端写内容
            ServletOutputStream out = response.getOutputStream();
            // 文件拷贝代码
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            in.close();
            out.close();
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    
    作者:kindleheart
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    常见SQL语句
    测试用例的设计
    移动端测试注意事项
    markdown编辑模式基本使用
    常用修改请求或返回方法
    前端性能测试工具Lighthouse
    presto环境部署
    pyenv管理python版本
    python2.6.6升级python2.7.14
    InfluxDB权限认证机制
  • 原文地址:https://www.cnblogs.com/kindleheart/p/9782586.html
Copyright © 2011-2022 走看看