基于表单的文件上传
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)设置表单的enctype为multipart/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(); } }