牛刀小试,一招搞定上传下载

本文介绍如何利用commons-fileupload组件实现文件上传功能,包括页面无刷新上传、上传进度监控及服务器响应状态码处理等特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


还是先一张图,来的更直接点





看到这个图也就明白我要写些什么了,没错使用commons-fileupload实现上传。

完成的主要需求是:

1、实现页面无刷新的上传(还是通过iframe实现),上传进度的监控。

2、采用fileupload组件比使用smartupload会更加减少服务器负载。

3、服务器端只返回响应的状态码,view进行响应的操作,更好的解耦。

4、简单的使用了jqueryui,实现一个简单的交互界面。

5、实现下载。


ok,废话不多说,进入正题看一下demo目录结构


一、核心类FileUploadTools.java用来解析request中的参数,并进行文件的上传保存。贴出代码。

package com.akwolf.upload;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * @author zhanghua
 *
 */
public class FileUploadTools {
	private HttpServletRequest request;
	private List<FileItem> items; // 全部上传内容
	private Map<String, List<String>> params = new HashMap<String, List<String>>(); // 保存�?��参数
	private Map<String, FileItem> files = new HashMap<String, FileItem>();
	private int maxSize = 30 * 1024 * 1024; // 默认�?��文件体积
	private String fileName = new Date().toString();
	private String[] allowedExts;
	private ServletFileUpload upload  ;

	/**
	 * FileUploadTools tool = null ; try{ tool = new
	 * FileUploadTools(request,1,this
	 * .getServletContext().getRealPath("/")+"temp") ;
	 * }catch(FileUploadException e){ if(e instanceof
	 * SizeLimitExceededException){ out.print("上传文件过大�?) ; return ; }
	 * 
	 * }
	 * 
	 * @param request
	 *            包含上传的request
	 * @param maxSize
	 *            最大上传体积
	 * @param tempDir
	 *            临时上传文件夹
	 * @throws FileUploadException
	 * @throws UnsupportedEncodingException
	 *             不支持上传的后缀名异常
	 */
	@SuppressWarnings("unchecked")
	public FileUploadTools(final HttpServletRequest request, int maxSize, String tempDir,boolean progress) throws FileUploadException,
			UnsupportedEncodingException {
		this.request = request;
		// 创建磁盘工厂
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 创建临时上传文件夹
		if (tempDir != null) {
			File tempFile = new File(tempDir);
			if (!tempFile.exists()) {
				tempFile.mkdir();
			}
			factory.setRepository(tempFile);
		}
		// buffer
		factory.setSizeThreshold(4096);

		upload = new ServletFileUpload(factory);
		if(progress){
			this.registProgressListener(request) ;
		}

		if (maxSize > 0) {
			this.maxSize = maxSize;
		}
		// 设置最大上传体积
		upload.setSizeMax(this.maxSize);
		try {
			// 解析上传request
			this.items = upload.parseRequest(this.request);
		} catch (FileUploadException e) {
			throw e;
		}
		this.init(this.fileName);
	}

	/**
	 * 解析请求,将表单输入域与文件域分开并存储在map中
	 * 
	 * @param fileName
	 * @throws UnsupportedEncodingException
	 */
	private void init(String fileName) throws UnsupportedEncodingException {
		Iterator<FileItem> iter = this.items.iterator();
		// 迭代每一个表单请求项
		while (iter.hasNext()) {
			FileItem item = iter.next();
			// 是否为表单域
			if (item.isFormField()) {
				// 取得输入项的名称
				String name = item.getFieldName();// 取得表单域的名称name="xxx"
				// 对应的值
				String value = new String(item.getString().getBytes("ISO-8859-1"), "UTF-8");
				// 存储所有表单项值
				List<String> temp = null;
				if (this.params.containsKey(name)) {
					// 已存在就直接取值
					temp = this.params.get(name);
				} else {
					// 不存在就创建数组
					temp = new ArrayList<String>();
				}
				temp.add(value);
				// 放入表单域中形式是 name-------value
				this.params.put(name, temp);
			} else {
				// 不是表单输入框,则可能是文件上传项
				String str = item.getName();
				String finalName = str.substring(str.lastIndexOf(File.separator) + 1);
				// 取出文件上传项存储起来 name ----file
				this.files.put(finalName, item);
			}
		}
	}

	/**
	 * 取得单�?的表单域,如:type="text"
	 * 
	 * @param name
	 * @return
	 */
	public String getParameter(String name) {
		String ret = null;
		List<String> list = this.params.get(name);
		if (list != null) {
			ret = list.get(0);
		}
		return ret;
	}

	/**
	 * 取得多�?的表单域,如:type="checkbox"
	 * 
	 * @param name
	 * @return
	 */
	public String[] getParameterValues(String name) {
		String[] ret = null;
		List<String> list = this.params.get(name);
		if (list != null) {
			ret = list.toArray(new String[] {});
		}
		return ret;
	}

	/**
	 * 取得上传文件
	 * 
	 * @return
	 */
	public Map<String, FileItem> getUploadFiles() {
		return this.files;
	}

	/**
	 * 指定存储路径和储存名�? 储存名不用带后缀�?
	 * 
	 * @param saveDir
	 *            指定存储路径
	 * @param saveName
	 *            指定存储文件的名称
	 * @return
	 * @throws Exception
	 */
	public List<UploadMsg> saveFile(String saveDir, String[] saveName) throws UnAllowedExtException {
		//System.out.println(saveDir+"--->"+saveName);
		List<UploadMsg> msgs = new ArrayList<UploadMsg>();
		long size = 0;
		// 存储随机生成的名称
		// List<String> names = new ArrayList<String>();
		// 创建存储目录
		File saveDiretory = new File(saveDir);
		if (!saveDiretory.exists()) {
			saveDiretory.mkdir();
		}
		// 如果有输入文件表单项
		if (this.files.size() > 0) {
			// 指定的文件名称与文件数目不相等
			if (files.size() != saveName.length) {
				throw new IllegalArgumentException("the saveName length is not match the file size!!");
			}
			// 上传文件后缀名
			String ext;
			// 取得文件表单项的名称
			Set<String> keys = this.files.keySet();
			// 迭代取出每个文件内容
			Iterator<String> iter = keys.iterator();
			// 用来创建进行存储的文件
			File saveFile = null;
			// 简单计数器,记录自己指定的名称
			int i = 0;
			boolean flag = true;
			while (iter.hasNext()) {
				String fileName = iter.next();
				// 后缀名的判断
				ext = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); // 不区分大小写
				for (int j = 0; j < allowedExts.length; j++) {
					if (ext.equals(allowedExts[j])) {
						flag = false;
						break;
					}
				}
				if (flag) {
					try {
						throw new UnAllowedExtException("不允许上传的文件");
					} catch (UnAllowedExtException e) {
						throw e;
					}
				}
				FileItem item = this.files.get(fileName);
				// 得到文件大小
				size = item.getSize();

				// 拼装出用户指定的文件名
				String saveFileName = saveName[i] + fileName.substring(fileName.lastIndexOf("."));
				// 添加到返回列表中
				//names.add(saveFileName);
				msgs.add(new UploadMsg(saveFileName, size)) ;
				saveFile = new File(saveDir + saveFileName);
				// 写入磁盘
				InputStream input;
				FileOutputStream fos;
				try {
					input = item.getInputStream();
					fos = new FileOutputStream(saveFile);
					byte[] b = new byte[512];
					while (input.read(b) != -1) {
						fos.write(b);
					}
					fos.close();
					input.close();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}

				// item.write(saveFile) ;
				// 删除临时文件
				item.delete();
				i++;
			}
		}
		return msgs;
	}

	public List<UploadMsg> saveFileRandomName(String saveDir) throws UnAllowedExtException {
		return this.saveFile(saveDir, new String[] { randomName() });
	}

	/**
	 * 
	 * 设置可上传的后缀名
	 * @param exts
	 */
	public void setAllowedExts(String[] exts) {
		this.allowedExts = exts;
	}
	
	/**
	 * 注册进度监听器
	 */
	public void registProgressListener(final HttpServletRequest request){
		upload.setProgressListener(new ProgressListener() {
			@Override
			public void update(long bytesRead, long contentLength, int items) {
				long percent = Math.round((double) bytesRead / contentLength
						* 100);
				request.getSession().setAttribute("percent", percent);
			}
		});
	}

	private String randomName() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		return sdf.format(new Date()) + getRandom();
	}

	/**
	 * 产生随机命名
	 * 
	 * @return
	 */
	private  String getRandom() {
		StringBuffer buffer = new StringBuffer();
		Random ran = new Random();
		for (int i = 0; i < 3; i++) {
			buffer.append(ran.nextInt(10));
		}
		return buffer.toString();
	}

}

二、UploadMsg.java封装上传后回传的信息类,里面的属性可以根据需要自行添加

package com.akwolf.upload;

/**
 * @Title: UploadMsg.java 
 * @author zhanghua
 * @date 2011-10-16 下午12:20:58 
 * @version V1.0
 * @Description: 保存上传后文件的信息的类
 */
public class UploadMsg {
	private String name;
	//单位 B
	private long size;

	public UploadMsg() {
	}

	public UploadMsg(String name, long size) {
		this.name = name;
		this.size = size;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public long getSize() {
		return size;
	}

	public void setSize(long size) {
		this.size = size;
	}

	@Override
	public String toString() {
		return "UploadMsg [name=" + name + ", size=" + size + "]";
	}
}

三、UnAllowedExtException.java自定义一个异常,用于对不支持后缀名的异常捕获,在前台进行显示。


四、建立一个进行业务处理的servlet(UploadServlet.java)

package com.akwolf.servlet;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;

import com.akwolf.upload.FileUploadTools;
import com.akwolf.upload.UnAllowedExtException;
import com.akwolf.upload.UploadMsg;

/**
 * @author zhanghua
 *
 */
public class UploadServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
			IOException {
		String action = request.getParameter("action");
		if ("upload".equals(action)) {
			doUpload(request, response);
		} else if ("download".equals(action)) {
			doDownload(request, response);
		}else if("progress".equals(action)){
			doProgress(request, response);
		}
	}

	/**
	 * 取得上传进度
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void doProgress(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		long percent = 0 ;
		if(request.getSession().getAttribute("percent")!=null) {
			percent = (Long)request.getSession().getAttribute("percent") ;
		}
		
		StringBuilder builder = new StringBuilder();
		builder.append("<percent>").append(percent).append("</percent>") ;
		response.setContentType("text/xml") ;
		response.getWriter().write(builder.toString()) ;
	}

	/**
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void doUpload(HttpServletRequest request, HttpServletResponse response) throws IOException {
		response.setContentType("text/html");
		FileUploadTools fut = null;
		// 闲着上传文件后缀名
		String[] exts = { "gif", "jpg", "png", "bmp","doc","docx","zip" };
		List<UploadMsg> list = new ArrayList<UploadMsg>();
		//String at = request.getParameter("articleId");
		// warning在进行request解析之前要进行乱码的处理
		request.setCharacterEncoding("UTF-8");
		
		StringBuilder builder = new StringBuilder() ;
		builder.append("<msg>") ;
		try {
			fut = new FileUploadTools(request, 300 * 1024 * 1024, this.getServletContext().getRealPath("/") + "temp",true);
			//fut.registProgressListener(request.getSession())  ;
			fut.setAllowedExts(exts);
			list = fut.saveFileRandomName(this.getServletContext().getRealPath("/") + "uploadfile"
					+ java.io.File.separator);
			UploadMsg uploadMsg = list.get(0);
			System.out.println(uploadMsg);

			// 遍历返回上传文件的重命名
			Iterator iters = list.iterator();
			builder.append("ok").append("</msg>") ;
		} catch (UnsupportedEncodingException e) {
			//e.printStackTrace();
			builder.append("unSupportedEncoding").append("</msg>") ;
		} catch (FileUploadException e) {
			if(e instanceof SizeLimitExceededException){
				builder.append("unSizeLimit").append("</msg>") ;
			}
			//e.printStackTrace();
		} catch (UnAllowedExtException e) {
			builder.append("unAllowedExt").append("</msg>") ;
			//e.printStackTrace() ;
			//不支持的文件后缀名
			//response.getWriter().write(
			//		"<script type=\"text/javascript\"> parent.document.alert('只允许上传jpg,gif,png,bmp格式的图片');</script>");
		}
		response.getWriter().write(builder.toString()) ;
	}

	/**
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void doDownload(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 取得下载文件的名称
		String name = request.getParameter("fileName");

		// name = "20111013165257234281.png";

		// web绝对路径
		String path = request.getSession().getServletContext().getRealPath("/");
		String savePath = path + File.separator + "uploadfile";

		// 设置为下载application/x-download
		response.setContentType("application/x-download");
		// 即将下载的文件在服务器上的绝对路径
		String filenamedownload = savePath + File.separator + name;
		// 下载文件时显示的文件保存名称
		String filenamedisplay = name;
		// 中文编码转换
		filenamedisplay = URLEncoder.encode(filenamedisplay, "UTF-8");
		response.addHeader("Content-Disposition", "attachment;filename=" + filenamedisplay);
		java.io.OutputStream os = response.getOutputStream();
		java.io.FileInputStream fis = new java.io.FileInputStream(filenamedownload);
		ServletOutputStream out = response.getOutputStream();
		try {

			byte[] b = new byte[1024];
			int i = 0;
			while ((i = fis.read(b)) > 0) {
				os.write(b, 0, i);
			}

		} catch (Exception e) {
			out.print("<script language=javascript>window.alert('file not found');history.back();</script>");
		} finally {
			out.close();
			fis.close();
			os.flush();
			os.close();
		}
	}
}

ok,到这里整个下载和上传功能基本实现。剩下简单的内容就打包好给大家下载了(代码贴的太多了尴尬),好了洗洗睡觉了。

http://download.youkuaiyun.com/detail/akwolf/3839604



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值