基于表单的文件上传

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();
    }

}

 

posted on 2015-02-05 22:31  milan's  阅读(213)  评论(0编辑  收藏  举报