欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

上传下载的一个工具类

程序员文章站 2022-04-08 14:57:06
...

自己做了一个上传(利用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;
	}
	
}