Apache FileUpload文件上传

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mChenys/article/details/81750321

Apache 开源组织提供了一个用来处理表单文件上传的一个开源组件( Commons-fileupload ),该组件性能优异,并且其API使用极其简单,可以让开发人员轻松实现web文件上传功能,因此在web开发中实现文件上传功能,通常使用Commons-fileupload组件实现。

使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:Commons-fileupload和commons-io。commons-io 不属于文件上传组件的开发jar文件,但Commons-fileupload 组件从1.1 版本开始,它工作时需要commons-io包的支持。

fileupload组件工作流程

核心API—DiskFileItemFactory

DiskFileItemFactory 是创建 FileItem 对象的工厂,这个工厂类常用方法:

(1)构造函数,可设置缓存文件的大小,和关联缓存文件

public DiskFileItemFactory(int sizeThreshold, java.io.File repository)

(2)设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。

public void setSizeThreshold(int sizeThreshold)

扫描二维码关注公众号,回复: 4178014 查看本文章

(3)指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").

public void setRepository(java.io.File repository)

核心API—ServletFileUpload

ServletFileUpload 负责处理上传的文件数据,并将表单中每个输入项封装成一个 FileItem 对象中。

(1)判断上传表单是否为multipart/form-data类型,即是否是文件上传

static boolean isMultipartContent(HttpServletRequest request)

(2)解析request对象,并把表单中的每一个输入项包装成一个fileItem 对象,并返回一个保存了所有FileItem的list集合。

List<FileItem> parseRequest(HttpServletRequest request)

(3)设置单个上传文件的最大值

setFileSizeMax(long fileSizeMax)

(4)设置上传文件总量的最大值

setSizeMax(long sizeMax)

(5)设置编码格式,解决上传文件名乱码问题

setHeaderEncoding(java.lang.String encoding)

(6)实时监听文件上传状态

setProgressListener(ProgressListener pListener)

核心API—FileItem

FileItem 用来表示文件上传表单中的一个上传文件对象或者普通表单对象

boolean  isFormField() 判断FileItem是一个文件上传对象还是普通表单对象

(1)如果判断是一个普通表单对象

String  getFieldName()  获得普通表单对象的name属性

String  getString(String encoding) 获得普通表单对象的value属性,可以用encoding进行编码设置

(2)如果判断是一个文件上传对象

String  getName() 获得上传文件的文件名(有些浏览器会携带客户端路径)

InputStream getInputStream()  获得上传文件的输入流

delete()  在关闭FileItem输入流后,删除临时文件

上传文件的存放问题

文件存放位置

(1)为保证服务器安全,上传文件应保存在应用程序的WEB-INF目录下,或者不受WEB服务器管理的目录。

(2)为防止多用户上传相同文件名的文件,而导致文件覆盖的情况发生,文件上传程序应保证上传文件具有唯一文件名。

(3)为防止单个目录下文件过多,影响文件读写速度,处理上传文件的程序应根据可能的文件上传总量,选择合适的目录结构生成算法,将上传文件分散存储。

代码演示

文件上传基类

package blog.csdn.net.web.servlet;

import java.io.File;
import java.io.IOException;
import java.util.List;

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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import net.sf.json.JSONObject;
/**
 * 文件上传基类
 * @author mChenys
 *
 */
public abstract class BaseUploadServlet extends HttpServlet {

	// 上传配置
	private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 内存3MB
	private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 硬盘40MB
	private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=utf-8");
		// 检测是否为多媒体上传
		if (!ServletFileUpload.isMultipartContent(req)) {
			resp.getWriter().println("Error:表单必须包含 enctype=multipart/form-data");
		}

		// 配置上传参数
		File repository = new File(getServletContext().getRealPath("/temp"));
		if (!repository.exists()) {
			repository.mkdirs();
		}
		// 配置内存缓存大小和硬盘缓存位置
		DiskFileItemFactory factory = new DiskFileItemFactory(MEMORY_THRESHOLD, repository);

		// 配置ServletFileUpload
		ServletFileUpload upload = new ServletFileUpload(factory);
		// 设置最大文件上传值
		upload.setFileSizeMax(MAX_FILE_SIZE);
		// 设置最大请求值 (包含文件和表单数据)
		upload.setSizeMax(MAX_REQUEST_SIZE);
		// 中文处理
		upload.setHeaderEncoding("utf-8");
		// 解析请求的内容提取文件数据
		try {
			List<FileItem> formItems = upload.parseRequest(req);
			onFileUpload(formItems,req,resp);
		} catch (Exception e) {
			JSONObject json = new JSONObject();
			json.put("status", -1);
			json.put("msg", "上传失败");
			resp.getWriter().println(json);
		}
	}

	public abstract void onFileUpload(List<FileItem> formItems,HttpServletRequest req,HttpServletResponse resp) throws  Exception;
}

实现类

package blog.csdn.net.web.servlet;

import java.io.File;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.fileupload.FileItem;
import blog.csdn.net.web.domain.Product;
import blog.csdn.net.web.service.ProductService;
import blog.csdn.net.web.util.UploadUtils;

/**
 * 添加商品
 */
public class ProductAddServlet extends BaseUploadServlet {
	private static final long serialVersionUID = 1L;

	@Override
	public void onFileUpload(List<FileItem> formItems, HttpServletRequest req, HttpServletResponse resp)
			throws Exception {

		// 创建实体,保存数据到数据库
		Product product = new Product();
		// 迭代表单数据
		for (FileItem item : formItems) {
			if (!item.isFormField()) {
				// 处理文件上传

				String fileName = UploadUtils.getUUIDName(item.getName());
				String dirName = UploadUtils.getDir(fileName);

				// 设置最终存储的根目录,需要被览器端访问,放置在WebRoot下
				String uploadPath = req.getServletContext().getRealPath("/image" + dirName);
				// 保存文件到硬盘
				File uploadDir = new File(uploadPath);
				if (!uploadDir.exists()) {
					uploadDir.mkdirs();
				}
				File storeFile = new File(uploadPath, fileName);
				item.write(storeFile);
				
				product.setImage("image" + dirName + fileName);
			} else {
				// 处理其他表单项
				BeanUtils.setProperty(product, item.getFieldName(), item.getString("utf-8"));
			}

		}

		int success = new ProductService().addProduct(product);

		if (success != -1) { // 重定向到productList
			resp.sendRedirect(req.getContextPath() + "/productList");
		} else {
			resp.getWriter().println("添加商品失败");
		}
	}
}

 文件名和文件夹处理工具类

package blog.csdn.net.web.util;

import java.util.UUID;

public class UploadUtils {
	/**
	 * 获取随机名称
	 * @param realName 真实名称
	 * @return uuid
	 */
	public static String getUUIDName(String realName){
		//realname  可能是  1.jpg   也可能是  1
		//获取后缀名
		int index = realName.lastIndexOf(".");
		if(index==-1){
			return UUID.randomUUID().toString().replace("-", "").toUpperCase();
		}else{
			return UUID.randomUUID().toString().replace("-", "").toUpperCase()+realName.substring(index);
		}
	}

	/**
	 * 获取文件目录
	 * @param name 文件名称
	 * @return 目录
	 */
	public static String getDir(String uuidFileName){
		int hashcode  = uuidFileName.hashCode();
		System.out.println("hashcode: "+hashcode );
		String hex = Integer.toHexString(hashcode );
		int j=hex.length();
		for(int k=0;k<8-j;k++){
			hex="0"+hex;
		}
		System.out.println("hex:"+hex);
		return "/"+hex.charAt(0)+"/"+hex.charAt(1)+"/";
	}
	
}

猜你喜欢

转载自blog.csdn.net/mChenys/article/details/81750321