使用FileUpload实现Servlet的文件上传
简介
FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下的文件上传功能。
FileUpload链接
FileUpload 是基于Apache的Commons IO的,所以在使用之前需要先在BuildPath种添加Commons IO。
Commons IO链接
1.在项目种添加Commons IO和FileUpload
1.1下载Commons IO的最新版本
1.2下载FileUpLoad的最新版本
注:tar.gz是linux版本的
1.3分别把两个jar文件复制到项目文件夹下
个人喜欢放在WEB-INF>lib下:
分别对两个jar文件执行如下操作:
注意:两个jar文件都要Add to Build Path,另外别忘了在java文件里还要import
2.按照Apache官网给出的指导使用文件上传
官网指导链接
2.0在html文件或者jsp文件里创建一个上传文件的表单
这里我创建的是一个jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>文件上传</h1> <form method="POST" enctype="multipart/form-data" action="UpLoadFile" name="uploadForm"> 选择一个文件: <input type="file" name="upfile"><br/> <br/> <input type="submit" value="上传"> </form> </body> </html>
运行如下:
用到的一些类的说明:
DiskFileItemFactory——工厂类
ServletFileUpload——用于解析resquest,能从resquest中解析出装有FileItem对象的一个List
FileItem——每个FileItem的实例都包含一个文件以及该文件的其他一些属性(文件名、大小等)
注意:以下部分翻译自官网指导。原文链接
2.1使用FileUpload
FileUpload可以通过多种不同的方式使用,具体的使用方式取决于您的应用要求。最简单的方式,您将调用一种方法来解析servlet请求到一个List中。
2.2FileUpLoad是如何运行的
FileUpload可以解析一个请求(request),并向应用程序提供上传的items(上传的文件表单项目)的一个List。每个文件项目(items)都有一些你的应用程序可能感兴趣的属性,例如name、content type,每个items还能提供一个“InputStream”。
FileUpload使用FileItemFactory类来创建新的items,FileUpload附带的FileItemFactory类的实例将项目的数据存储在内存或磁盘上,具体取决于项目的大小(即数据字节数)。但是,可以自定义此行为。
2.3解析请求
在使用上传的items之前,需要解析请求本身,确保请求实际上是一个文件上传请求可用。
// Check that we have a file upload request boolean isMultipart = ServletFileUpload.isMultipartContent(request);
2.4最简单的一种使用情况
- 只要上传的项目足够小,应保留在内存中。
- 较大的项目应写入磁盘上的临时文件。
- 不应该允许非常大的上传请求。
- 内存中默认保留的内容的最大容量,上传请求的最大允许大小以及临时文件的位置是可以接受的(这一句是Google翻译的)
// 创建工厂(这里用的是工厂模式) DiskFileItemFactory factory = new DiskFileItemFactory(); //获取汽车零件清单与组装说明书(从ServletContext中得到上传来的数据) ServletContext servletContext = this.getServletConfig().getServletContext(); File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir"); //工厂把将要组装的汽车的参数录入工厂自己的系统,因为要根据这些参数开设一条生产线(上传来的文件的各种属性) factory.setRepository(repository); //此时工厂中已经有了汽车的组装工艺、颜色等属性参数(上传来的文件的大小、文件名等) //执行下面的这一行代码意味着根据组装工艺等开设了一条组装生产线 ServletFileUpload upload = new ServletFileUpload(factory);
这样我门就获得了一个List。
Servlet完整代码:
package com.feipeng8848; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; /** * Servlet implementation class UpLoadExcelServlet */ public class UpLoadExcelServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public UpLoadExcelServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>\n"); out.println("<head><title>PageTitle</title></head>"); out.println("<body>"); out.println("<p>文件已经上传成功</p>"); out.println("</body>"); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); System.out.println("doPost"); boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { System.out.println("True"); // 创建工厂(这里用的是工厂模式) DiskFileItemFactory factory = new DiskFileItemFactory(); //获取汽车零件清单与组装说明书(从ServletContext中得到上传来的数据) ServletContext servletContext = this.getServletConfig().getServletContext(); File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir"); //工厂把将要组装的汽车的参数录入工厂自己的系统,因为要根据这些参数开设一条生产线(上传来的文件的各种属性) factory.setRepository(repository); //此时工厂中已经有了汽车的组装工艺、颜色等属性参数(上传来的文件的大小、文件名等) //执行下面的这一行代码意味着根据组装工艺等开设了一条组装生产线 ServletFileUpload upload = new ServletFileUpload(factory); //解析请求 try { //把零件送给生产线,出来的就是一辆组装好的汽车(把request转成FileItem的实例) List<FileItem> items = upload.parseRequest(request); Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { FileItem item = iter.next(); //创建文件输出流 File file=new File("D:\\b.xlsx"); if(!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } FileOutputStream fos=new FileOutputStream(file); //创建输入流 InputStream fis=(InputStream) item.getInputStream(); //从输入流获取字节数组 byte b[]=new byte[1]; //读取一个输入流的字节到b[0]中 int read=fis.read(b); while(read!=-1) { fos.write(b,0,1); read=fis.read(b); } fis.close(); fos.flush(); fos.close(); //打印List中的内容(每一个FileItem的实例代表一个文件,执行这行代码会打印该文件的一些基本属性,文件名,大小等) System.out.println(item); } System.out.println("循环输出完成"); } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { System.out.println("False"); } } }
选择一个文件:
输出:
输出的完整内容:
doPost True name=PRICIPLE_k.png, StoreLocation=C:\Users\k\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\DBControler\upload_cae42561_32ce_45d4_9009_
ec94523a4b02_00000000.tmp, size=24914 bytes, isFormField=false, FieldName=upfile 循环输出完成