`
lhxctc
  • 浏览: 52215 次
  • 性别: Icon_minigender_1
  • 来自: 江西
社区版块
存档分类
最新评论

上传下载的一个工具类

    博客分类:
  • Java
阅读更多

自己做了一个上传(利用apache-fileupload组件)下载的一个封装、希望对大家有帮组.请看下面例子。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;

/**
 * @autor MingMing
 */
public class FileHandler {
	
	/**
	 * 所有上传文件的总长度最大值
	 */
	private long SUM_MAX_SIZE = 50 * 1024 * 1024;
	/**
	 * 允许上传的文件默认最大值
	 */
	private long MAX_SIZE = 10 * 1024 * 1024;
	
	/**
	 * 允许上传的文件类型
	 */
	private String[] allowedExt = new String[] { "jpg", "jpeg", "gif", "txt",
			"doc", "docx", "mp3", "wma", "m4a" };
	
	/**
	 * 用完item需delete缓存文件
	 */
    private Map<String,List<FileItem>> files;
    
    private Map<String,List<String>> parameters;
	
		/**
	 * 设置输出字符集
	 */
	private String ENCODING = "UTF-8";
	
	/**
	 * @param SUM_MAX_SIZE 允许所有文件总长度最大值,当赋值0时使用默认,默认值是50M, 为-1时无限制
	 * @param MAX_SIZE 允许单个上传文件最大长度是,当赋值0时使用默认,默认值10M,为-1时无限制
	 * @param ENCODING 输出字符集,默认UTF-8
	 * @param allowedExt 上传文件类型,当没有传送值时则表示任何类型文件都允许
	 */
	public FileHandler(long SUM_MAX_SIZE,long MAX_SIZE,String ENCODING,String[] allowedExt) {
		if (SUM_MAX_SIZE != 0) 
			this.SUM_MAX_SIZE = SUM_MAX_SIZE;
		if (MAX_SIZE != 0) 
			this.MAX_SIZE = MAX_SIZE;
		if (ENCODING != null)
			this.ENCODING = ENCODING;
		this.allowedExt = allowedExt;
	}
	
	public FileHandler() {
		
	}
	
	public FileHandler upload(HttpServletRequest request) throws UploadException {
		RequestContext context = new ServletRequestContext(request);
		if(!ServletFileUpload.isMultipartContent(context)) {//判断form表单的传输方式是否是多数据类型
			throw new UploadException("您所提供表单类型不是多数据类型multipart-formdata");
		}
		/**
		 * 实例化一个硬盘文件工厂,用来配置上传组件ServletFileUpload
		 */
		DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
		diskFileItemFactory.setSizeThreshold(4096);// 设置上传文件时用于临时存放文件的内存大小,这里是4K.多于的部分将临时存在硬盘
		/**
		 * 采用系统临时文件目录作为上传的临时目录
		 */
		File tempfile = new File(System.getProperty("java.io.tmpdir"));
		diskFileItemFactory.setRepository(tempfile);
		/**
		 * 用以上工厂实例化上传组件 设置最大上传尺寸
		 */
		ServletFileUpload fileUpload = new ServletFileUpload(
				diskFileItemFactory);
		/**
		 * 单个文件最大的大小
		 */
		fileUpload.setFileSizeMax(MAX_SIZE);//fileSizeMax = -1 没有上限
		 /**
		 * 整个request中最大上限值(包含所有表单[文本域、文件域])
		 */
		fileUpload.setSizeMax(SUM_MAX_SIZE);//sizeMax = -1 没有上限
		/**
		 * 调用FileUpload.settingHeaderEncoding(”UTF-8″),这项设置可以解决路径或者文件名为乱码的问题。
		 * 设置输出字符集
		 */
		fileUpload.setHeaderEncoding(ENCODING);
		try {
			List<FileItem> items = fileUpload.parseRequest(request);
			if (items == null || items.size() == 0) {
				throw new UploadException("没有上传一个正确文件!");
			}
			parameters = new HashMap<String, List<String>>();
			files = new HashMap<String, List<FileItem>>();
			for (FileItem item: items) {
				String fieldName = item.getFieldName();//文本框名称 <input name="">
				if (item.isFormField()) {//简单文本域
					/**
					 * 在取字段值的时候,用FileItem.getString(”UTF-8″),这项设置可以解决获取的表单字段为乱码的问题。
					 */
					String value = item.getString(ENCODING);//文本框的值
					List<String> values;
					if (parameters.get(fieldName) != null) {
                        values = parameters.get(fieldName);
                    } else {
                        values = new ArrayList<String>();
                    }
					values.add(value);
					parameters.put(fieldName, values);
				}else { //文件域
					long fileLength = item.getSize();
					if (fileLength == 0) {
						throw new UploadException("文件为空或非法文件!");
					}
					String userPath = item.getName();//完整路径 C:\sdss\ssss\sss.xls
					String fileName = userPath.substring(userPath.lastIndexOf("\\") + 1); //文件名 sss.xls
					String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); //XLS
					//检测文件的后缀名合法性
					if (! (allowedExt == null || allowedExt.length == 0) ){
						boolean extBoo = false;
						for (String ext: allowedExt) {
							if (ext.toLowerCase().equals(fileExt)) {
								extBoo = true;
								break;
							}
						}
						if (!extBoo){//不合法
							throw new UploadException("请选择正确得文件格式,包含" + Arrays.toString(allowedExt));
						}
					}
                    List<FileItem> values;
                    if (files.get(fieldName) != null) {
                        values = files.get(fieldName);
                    } else {
                        values = new ArrayList<FileItem>();
                    }
                    values.add(item);
                    files.put(item.getFieldName(), values);
				}
			}
		} catch (FileUploadBase.SizeLimitExceededException e) {
			throw new UploadException("01-请求数据的size超出了规定的大小",e);
		} catch (FileUploadBase.FileSizeLimitExceededException e) {
			throw new UploadException("02-请求文件的size超出了规定的大小",e);
		} catch (FileUploadBase.IOFileUploadException e) {
			throw new UploadException("03-文件传输出现错误,例如磁盘空间不足等");
		} catch (FileUploadBase.InvalidContentTypeException e) {
			throw new UploadException("04-无效的请求类型,即请求类型enctype != \"multipart/form-data\"");
		} catch (FileUploadException e) {
			throw new UploadException("00-上传失败,原因不明.",e);
		} catch (UnsupportedEncodingException e) {
			throw new UploadException("您提供编码不能识别["+ENCODING+"]",e);
		}
		return this;
	}
	
	/**
	 * 模仿 request.getParameter()
	 * @param name
	 * @return
	 */
	public String getParameter(String name) {
		List<String> v = (List<String>) parameters.get(name);
		if (v != null && v.size() > 0) {
			return v.get(0);
		}
		return null;
	}
	/**
	 * 模仿 request.getParameterNames();
	 * @return
	 */
	public Enumeration<String> getParameterNames() {
        return Collections.enumeration(parameters.keySet());
    }
	
	/**
	 * 模仿 request.getParameterValues(); 
	 * @param name
	 * @return
	 */
	public String[] getParameterValues(String name) {
        List<String> v = parameters.get(name);
        if (v != null && v.size() > 0) {
            return (String[]) v.toArray(new String[v.size()]);
        }
        return null;
    }
	
	/**
	 * 获取文本域的ContentType
	 * @param fieldName
	 * @return
	 */
	public String[] getContentType(String fieldName) {
		List<FileItem> items = (List<FileItem>) files.get(fieldName);
		if (items == null) {
			return null;
		}
		List<String> contentTypes = new ArrayList<String>(items.size());
		for (int i = 0; i < items.size(); i++) {
			FileItem fileItem = (FileItem) items.get(i);
			contentTypes.add(fileItem.getContentType());
		}
		return (String[]) contentTypes.toArray(new String[contentTypes.size()]);
	}
	/**
	 * 模仿文本域得request.getParameterNames();
	 * @return
	 */
	public Enumeration<String> getFileParameterNames() {
        return Collections.enumeration(files.keySet());
    }
	/**
	 * 根据文本域表单名称获取文件
	 * @param fieldName
	 * @return
	 */
	public File[] getFile(String fieldName) {
		List<FileItem> items = (List<FileItem>) files.get(fieldName);
		if (items == null) {
			return null;
		}
		List<File> fileList = new ArrayList<File>(items.size());
		for (int i = 0; i < items.size(); i++) {
			DiskFileItem fileItem = (DiskFileItem) items.get(i);
			fileList.add(fileItem.getStoreLocation());
		}
		return (File[]) fileList.toArray(new File[fileList.size()]);
	}
	
	/**
	 * @param fieldName
	 * @return
	 */
	public String[] getFileNames(String fieldName) {
		List<FileItem> items = files.get(fieldName);
		if (items == null) {
			return null;
		}
		List<String> fileNames = new ArrayList<String>(items.size());
		for (int i = 0; i < items.size(); i++) {
			DiskFileItem fileItem = (DiskFileItem) items.get(i);
			fileNames.add(getCanonicalName(fileItem.getName()));
		}
		return (String[]) fileNames.toArray(new String[fileNames.size()]);
	}
	private String getCanonicalName(String filename) {
		int forwardSlash = filename.lastIndexOf("/");
		int backwardSlash = filename.lastIndexOf("\\");
		if (forwardSlash != -1 && forwardSlash > backwardSlash) {
			filename = filename.substring(forwardSlash + 1, filename.length());
		} else if (backwardSlash != -1 && backwardSlash >= forwardSlash) {
			filename = filename.substring(backwardSlash + 1, filename.length());
		}
		return filename;
	}
	
	
	
	/**
	 * 该方法支持支持国际化 但是文件名不能超过17个汉字 而且在IE6下存在bug
	 */
	public void downloadI18NFile(HttpServletRequest request,HttpServletResponse response,File src,String showFileName) throws Exception {
		if (src == null || !src.exists() || src.length() == 0) {
			throw new RuntimeException("系统找不到可用资源!");
		}
		java.io.BufferedInputStream bis = null;
		java.io.BufferedOutputStream bos = null;
		try {
			long fileLength = src.length();
			showFileName = URLEncoder.encode(showFileName, "UTF-8");
			String mimeType = request.getSession().getServletContext().getMimeType(src.getName());
			mimeType = (mimeType != null)?(mimeType):("application/x-msdownload"); //"application/octet-stream"
			System.out.println("mimeType=" + mimeType);
			response.setContentType(mimeType);
			response.setHeader("Content-disposition", "attachment; filename="
					+ showFileName);
			//response.setHeader("Content-disposition", "filename="
				  //+ showFileName);//打开
			response.setHeader("Content-Length", String.valueOf(fileLength));
			bis = new BufferedInputStream(new FileInputStream(src));
			bos = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			throw new RuntimeException("下载失败",e);
		} finally {
			try {
				if (bis != null)	bis.close();
			}catch(IOException ex) {
				throw new RuntimeException("关闭资源失败",ex);
			}finally {
				try{
					if (bos != null) bos.close();
				}catch(IOException ex) {
					throw new RuntimeException("关闭资源失败",ex);
				}
			}
		}
	}
	
	/**
	 * 下载文件. 支持中文,文件名长度无限制 不支持国际化
	 * @param request
	 * @param response
	 * @param src
	 * @param showFileName
	 * @throws Exception
	 */
	public void downloadFile(HttpServletRequest request,HttpServletResponse response,File src,String showFileName) {
		if (src == null || !src.exists() || src.length() == 0) {
			throw new RuntimeException("系统找不到可用资源!");
		}
		java.io.BufferedInputStream bis = null;
		java.io.BufferedOutputStream bos = null;
		try {
			long fileLength = src.length();
			bis = new BufferedInputStream(new FileInputStream(src));
			//response.setContentType("text/html;charset=utf-8");
			String mimeType = request.getSession().getServletContext().getMimeType(src.getName());
			mimeType = (mimeType != null)?(mimeType):("application/x-msdownload"); //"application/octet-stream"
			response.setContentType(mimeType);
			//response.setContentType("application/x-msdownload;");
			response.setHeader("Content-disposition", "attachment; filename="
					+ new String(showFileName.getBytes("GBK"), "ISO8859-1"));//打开、保存
			//response.setHeader("Content-disposition", "filename="
					//+ new String(showFileName.getBytes("GBK"), "ISO8859-1"));//打开
			response.setHeader("Content-Length", String.valueOf(fileLength));
			bos = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			throw new RuntimeException("下载失败",e);
		} finally {
			try {
				if (bis != null)	bis.close();
			}catch(IOException ex) {
				throw new RuntimeException("关闭资源失败",ex);
			}finally {
				try{
					if (bos != null) bos.close();
				}catch(IOException ex) {
					throw new RuntimeException("关闭资源失败",ex);
				}
			}
		}
	}
	
	/**
     * @param req  the request.
     * @return a new request context.
     */
    private RequestContext createRequestContext(final HttpServletRequest req) {
        return new RequestContext() {
            public String getCharacterEncoding() {
                return req.getCharacterEncoding();
            }
            public String getContentType() {
                return req.getContentType();
            }
            public int getContentLength() {
                return req.getContentLength();
            }
            public InputStream getInputStream() throws IOException {
                return req.getInputStream();
            }
        };
    }

	public Map<String, List<FileItem>> getFiles() {
		return files;
	}

	public void setFiles(Map<String, List<FileItem>> files) {
		this.files = files;
	}

	public Map<String, List<String>> getParameters() {
		return parameters;
	}

	public void setParameters(Map<String, List<String>> parameters) {
		this.parameters = parameters;
	}
	public static class UploadException extends Exception{
		private static final long serialVersionUID = -6797554437005471992L;
		
		public UploadException() {
			super();
		}
		public UploadException(String message, Throwable cause) {
			super(message, cause);
		}

		public UploadException(String message) {
			super(message);
		}

		public UploadException(Throwable cause) {
			super(cause);
		}
	}
	////////////////////////////////////////////////////FileUtil
	public static String byteCountToDisplaySize(long size) {
		String displaySize;
		if (size / 1073741824L > 0L)
			displaySize = String.valueOf(size / 1073741824L) + " GB";
		else if (size / 1048576L > 0L)
			displaySize = String.valueOf(size / 1048576L) + " MB";
		else if (size / 1024L > 0L)
			displaySize = String.valueOf(size / 1024L) + " KB";
		else {
			displaySize = String.valueOf(size) + " bytes";
		}
		return displaySize;
	}
	
}
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics