• 文件上传下载学习笔记


    基于表单的文件上传

    1.form表单设计如下

      <form action="uploadServlet" method="post" enctype="multipart/form-data">
              file:<input type="file" name="file"/>
              <input type="submit" value="submit"/>
         </form>

       注意:(1)由于get提交数据大小有限(且各浏览器不一样),而理论上,POST是没有大小限制的,所以一定要用POST方式发送请求

                  (其实服务器的处理程序的处理能力会限制POST,如:Tomcat默认2M;但是我们可以通过修改tomcat目录下的conf目录下的server.xml 文件

                        <Connector>标签的maxPostSize="0"设置取消POST的大小限制)

              (2)form表单域用<input type="file" name="file"/>

              (3)设置表单的enctypemultipart/form-data,用2进制传输数据传输数据

    2.commons-fileupload组件

      (1)简介

        上面表单提交数据后:服务器端获取提交的数据

         a. 这里无法用request.getParameter(String name)获取提交的文件信息;由于是用二进制传输数据的,所以我们可以考虑使用IO流

             用request.getInpustStream()获取流后读取信息;但由于上传文件可能是图片等类型,转换复杂,不建议使用

         b. apache提供了工具commons-fileupload组件和他的依赖包commons-io,处理表单文件上传,它可以支持任意大小的文件的上传

     (2)原理

          a.FileUpload can parse such a request and provide your application with a list of the individual uploaded items. Each such item implements

       the FileItem interface, regardless of its underlying implementation.

          将请求中所有信息(无论是文本域还是文件域)解析成一个个FileItem,得到一个FileItem List

          b.Each file item has a number of properties that might be of interest for your application. For example, every item has a name and a content

         type, and can provide an InputStream to access its data. On the other hand, you may need to process items differently, depending upon

       whether the item is a regular form field - that is, the data came from an ordinary text box or similar HTML field - or an uploaded file.

       The FileItem interface provides the methods to make such a determination, and to access the data in the most appropriate manner.

           通过判断是文本域还是文件域执行不同操作

     (2)使用

       a.加入相关jar包:commons-fileupload.jar、commons-io.jar

       b.判断请求是否为上传文件请求

    // Check that we have a file upload request
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

       c.解析request,获取List<FileItem>

          简单写法:

    // Create a factory for disk-based file items
    DiskFileItemFactory factory = new DiskFileItemFactory();
    
    // Configure a repository (to ensure a secure temp location is used)
    ServletContext servletContext = this.getServletConfig().getServletContext();
    File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
    factory.setRepository(repository);
    
    // Create a new file upload handler
    ServletFileUpload upload = new ServletFileUpload(factory);
    
    // Parse the request
    List<FileItem> items = upload.parseRequest(request);

      复杂写法:可以设置限制条件和其他属性

    // Create a factory for disk-based file items
    DiskFileItemFactory factory = new DiskFileItemFactory();
    
    // 设置内存中最可以存放的文件大小,超过这个大小,就将文件写到一个临时文件中,单位为byte,文件过大或多线程时占据大量内存
    factory.setSizeThreshold(yourMaxMemorySize);
    // 设置临时文件 factory.setRepository(yourTempDirectory);
    // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // 设置上传文件的总大小的最值,也可以通过setFileSizeMax(maxSize)设置单个文件最大值 upload.setSizeMax(yourMaxRequestSize); // Parse the request List<FileItem> items = upload.parseRequest(request);

    d.遍历List根据不同域类型,执行不同操作

    // Process the uploaded items
    Iterator<FileItem> iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = iter.next();
    
        if (item.isFormField()) {
            processFormField(item);
        } else {
            processUploadedFile(item);
        }
    }

        文本域

    // Process a regular form field
    if (item.isFormField()) {
        String name = item.getFieldName();
        String value = item.getString();
        ...
    }

      文件域

    // Process a file upload
    if (!item.isFormField()) {
        String fieldName = item.getFieldName();
        String fileName = item.getName();
        String contentType = item.getContentType();
        boolean isInMemory = item.isInMemory();
        long sizeInBytes = item.getSize();
        ...
    }

     具体可以查看http://commons.apache.org/proper/commons-fileupload/using.html

    文件下载

       1.通知客户端浏览器:这是一个要下载的文件,不再按.html的方式打开

           设置响应类型,Content-Type:application/x-msdownload

        2.通知客户端浏览器:不再由浏览器处理该文件,而是交给用户自行处理

          设置响应头;Content-Disposition,该报头指定了接收程序处理数据内容的方式,在 HTTP 应用中只有 attachment 是标准方式,

          attachment 表示要求用户干预。在 attachment 后面还可以指定 filename 参数,该参数是服务器建议浏览器将实体内容保存到

          文件中的文件名称。

       3.具体的文件:可以调用response.getOutputStream(),以IO流发送给客户端

         如下为具体代码演示:

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class FileDownloadServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            //1.设置响应类型,Content-Type:application/x-msdownload
            response.setContentType("application/x-msdownload");
            
            //2.设置响应头;Content-Disposition
            response.setHeader("Content-Disposition", "attachment;filename=abc.docx");
            
            //3.调用response.getOutputStream(),以IO流发送给客户端
            OutputStream out = response.getOutputStream();
            
            String downloadFile = "C:\Users\milan\Desktop\bug.docx";
            
            InputStream in = new FileInputStream(downloadFile);
            byte[] buf = new byte[1024];
            int len = 0;
            while((len=in.read(buf))!=-1){
                out.write(buf, 0, len);
            }
            
            in.close();
        }
    
    }
  • 相关阅读:
    前端错误监控上报公共方法,可在父页面及iframe子页面同时使用
    python3.7爬取墨菲定律保存在本地txt
    实现一个左滑删除功能
    用docsify快速构建文档,并用GitHub Pages展示
    最常用的快捷键总结
    有价值的帖子或博客链接
    解决8080端口占用问题
    用gulp构建你的前端项目
    移动端右侧栏导航面板
    自己封装一个弹框插件
  • 原文地址:https://www.cnblogs.com/javamilan/p/4276085.html
Copyright © 2020-2023  润新知