- commons-fileupload框架源码解析(一)--实例
- commons-fileupload框架源码解析(二)--HTTP
- commons-fileupload框架源码解析(三)--ParseRequest
- commons-fileupload框架源码解析(四)--FileItemIterator
- commons-fileupload框架源码解析(五)--MultipartStream
- commons-fileupload框架源码解析(六)--ParameterParser
- commons-fileupload框架源码解析(七)--FileCleaningTracker
- commons-fileupload框架源码解析(八)--DeferredFileOutputStream
前言
commons-fileupload虽然我经常会在项目里用的,它有非常强大的文件上传功能,虽然经常用,却不曾了解过其源码的实现,为了让自己更加牛B,更好的掌握文件上传的原理和具体实现方式,我开始了长达一个月的解析该框架源码的工作,总算将框架的实现原理给摸清。是时候写一系列博客来装B,comons-fileupload的版本是1.4
第一章简介
第一章的我并不是马上讲起原理,而是直接我的用例展现出来,我打算通过该用例去解析其原理。
用例
只是一个普通的JavaWeb项目,代码的实现都在FileUploadServlet里
目录结构截图

项目目录结构.png
pom.xml
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
FileUploadServlet
package bin.study;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Iterator;
import java.util.List;
/**
* 实现文件上传的Servlet
* @author Administrator
*
*/
public class FileUploadServlet extends HttpServlet {
//上传路径
private File uploadPath;
//当文件过大时,需要设置一个临时路径
private File tempPath;
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
DiskFileItemFactory factory = new DiskFileItemFactory();
// 内存存储的最大值
factory.setSizeThreshold(4096);
factory.setRepository(tempPath);
ServletFileUpload upload = new ServletFileUpload(factory);
//设置文件上传大小
upload.setSizeMax(1000000 * 20);
try {
List fileItems = upload.parseRequest(req);
String itemNo = "";
for (Iterator iter = fileItems.iterator(); iter.hasNext(); ) {
FileItem item = (FileItem) iter.next();
//是普通的表单输入域
if (item.isFormField()) {
if ("itemNo".equals(item.getFieldName())) {
itemNo = item.getString();
}
}
//是否为input="type"输入域
if (!item.isFormField()) {
String fileName = item.getName();
long size = item.getSize();
if ((fileName == null || fileName.equals("")) && size == 0) {
continue;
}
//截取字符串 如:C:\WINDOWS\Debug\PASSWD.LOG
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1, fileName.length());
//item.write(new File(uploadPath + itemNo + ".gif"));
item.write(new File(uploadPath, itemNo + ".gif"));
}
}
//重定向页面
res.sendRedirect(req.getContextPath() + "/servlet/item/SearchItemServlet");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 初始化方法,设定目录
*/
public void init() throws ServletException {
uploadPath = new File(getServletContext().getRealPath("upload"));
//System.out.println("uploadPath=====" + uploadPath);
//如果目录不存在
if (!uploadPath.exists()) {
//创建目录
uploadPath.mkdir();
}
//临时目录
tempPath = new File(getServletContext().getRealPath("temp"));
if (!tempPath.exists()) {
tempPath.mkdir();
}
}
}
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>fileUploadServlet</servlet-name>
<servlet-class>bin.study.FileUploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>fileUploadServlet</servlet-name>
<url-pattern>/fileUploadServlet</url-pattern>
</servlet-mapping>
</web-app>