文件上传细节详解

直接上代码,项目中可以直接使用的

package com.gyarmy.upload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

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

/*
 *  处理 文件上传的 servlet 
 * 	
 * 
 * 		导包 :   commons-fileupload-1.2.1.jar
 		commons-io-1.4.jar
 * 
 */
public class UploadServlet2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 弄一个数组, 里面写上 允许的 文件的 扩展名
		String[] extensions = { ".png", ".bmp", ".gif", ".jpg", ".avi",
				".rmvb", ".doc", ".txt" };

		// 判断是否是 文件上传的 请求, 如果不是 , 那么就给用户一个 友好的提示
		if (!ServletFileUpload.isMultipartContent(request)) {

			// 如果进来, 则说明不是文件上传的 请求, 那么就给用户提示, 请先设置 表单 相关的属性 之后 再 提交请求
			request.setAttribute("message", "对不起, 不是文件上传的表单, 请检查 相关的属性 设置...");

			request.getRequestDispatcher("/message.jsp").forward(request,
					response);
			return;
		}

		try {
			DiskFileItemFactory factory = new DiskFileItemFactory();

			// 设置 临时缓冲区 所在的文件夹
			// 一般开发过程中, 上传的文件是保存在 当前的 web工程下的 .

			// 临时 缓冲区 产生的缓存 文件 的位置
			factory.setRepository(new File(getServletContext().getRealPath(
					"/temp")));
			factory.setSizeThreshold(1024 * 1024); // 设置临时缓冲区的大小 是 1M

			// 拿到 解析器 对象
			ServletFileUpload parser = new ServletFileUpload(factory);
			parser.setHeaderEncoding("UTF-8");

			// 设置单个的上传的文件的大小
			parser.setFileSizeMax(1024 * 1024 * 2); // 单个 文件不能超过 2M

			// 设置总 的上传的文件的大小
			parser.setSizeMax(1024 * 1024 * 20); // 总文件 大小 文件不能超过 20 M

			// 设置 一个 进度 监听器, 设置了之后, 解析器 就会自动去调用 监听器的 方法 update
			parser.setProgressListener(new ProgressListener() {

				// pBytesRead ---当前 读到的 数据 是 多少了
				// pContentLength ---当前 解析到的fileItem的长度是多少
				// pItems ---当前 解析到第几个item了

				private long megaBytes = -1;

				public void update(long pBytesRead, long pContentLength,int pItems) {
					
//					第一次 :  400000 ------- 0  ---0     megaBytes   0
//					第二次 :  800000 ------- 0  ---0     
//					第二次 : 1100000 ------- 1  ---1     megaBytes   1 
//					第二次 : 1900000 ------- 1  ---1     megaBytes   1 
//					第二次 : 2200000 ------- 2  ---2     megaBytes   2 
					
					long mBytes = pBytesRead / 1000000;
					if (megaBytes == mBytes) {
						return;
					}
					megaBytes = mBytes;
					System.out.println("We are currently reading item "
							+ pItems);
					if (pContentLength == -1) {
						System.out.println("So far, " + pBytesRead
								+ " bytes have been read.");
					} else {
						System.out.println("So far, " + pBytesRead + " of "
								+ pContentLength + " bytes have been read.");
					}
				}
			});

			List<FileItem> list = parser.parseRequest(request);
			
			for (FileItem fileItem : list) {
				if (fileItem.isFormField()) {
					// 说明是普通输入项
					// 获得提交过来的参数的名称
					String fieldName = fileItem.getFieldName();
					String value = fileItem.getString("UTF-8");

					System.out.println(fieldName + " = " + value);
				} else {
					// 说明是 文件上传 输入项
					// 获得文件的名称

					// C:\Users\Administrator\Desktop\aaa.txt
					// aaa.txt
					String filename = fileItem.getName();

					// 要去特殊 处理
					int lastIndexOf = filename.lastIndexOf("\\");

					if (lastIndexOf != -1) {

						// 说明 是 C:\Users\Administrator\Desktop\aaa.txt

						// aaa.txt
						filename = filename.substring(lastIndexOf + 1);
					}

					// aaa.txt
					int index = filename.lastIndexOf(".");

					// 拿到 上传的文件的扩展名
					String fileExt = filename.substring(index);

					String exts = Arrays.toString(extensions);

					if (!exts.contains(fileExt)) {

						// 友好提示, 对不起, 你上传的文件 不在 运行的范围内
						request.setAttribute("message", "您上传的   " + fileExt
								+ "类型是 不符合  规范的 ...");

						request.getRequestDispatcher("/message.jsp").forward(
								request, response);

					}

					// 定义 一个输出流
					// File file = new File(getServletContext().getRealPath(
					// "/WEB-INF/upload"));
					// // f:\\aa\bb..\\upload\aa.txt
					// //
					// f:\\aa\bb..\\upload\C:\Users\Administrator\Desktop\aaa.txt

					String realPath = getServletContext().getRealPath(
							"/WEB-INF/upload");

					// 生成随机 文件夹
					String savePath = generateSavePath(realPath, filename);

					String uuidname = generateUUIDName(filename);

					// 获得文件的输入 流
					InputStream in = fileItem.getInputStream();

					// 将上传 的文件写到 生成 的随机文件夹 中保存起来
					OutputStream out = new FileOutputStream(new File(savePath,
							uuidname));

					// io 流对拷
					byte[] buf = new byte[1024];
					int len = 0;
					while ((len = in.read(buf)) > 0) {
						out.write(buf, 0, len);
					}
					// 关闭流
					in.close();
					out.close();

					// 将上传时 产生的临时文件 删掉 ...
					fileItem.delete();
				}
			}
		} catch (FileUploadBase.FileSizeLimitExceededException e) {

			request.setAttribute("message", "对不起, 单个文件大小不能超过 	2M ...");

			request.getRequestDispatcher("/message.jsp").forward(request,
					response);
			return;
		} catch (FileUploadBase.SizeLimitExceededException e) {

			request.setAttribute("message", "对不起,  总  文件大小不能超过 	20 M ...");
			request.getRequestDispatcher("/message.jsp").forward(request,
					response);
			return;
		} catch (Exception e) {
			e.printStackTrace();
		}

		response.setContentType("text/html;charset=utf-8");
		response.getWriter().print("上传成功....");

		
		response.setHeader("content-disposition", "attachement;filename=aa.txt");
		
		
		//还需要将  要下载的 文件 当作 一个 inputStream 流 读进来, 
		// 读进来 再 写到   response.getOutputStream中去就可以了. 
		
	}

	// 生成全球唯一的 名字
	private String generateUUIDName(String filename) {

		// 04e78bd1-3c94-41d5-ad36-01f2eab33801_aaa.txt
		return UUID.randomUUID().toString() + "_" + filename;

	}

	// 生成 随机的文件夹
	private String generateSavePath(String realPath, String filename) {
		int hashCode = filename.hashCode();

		int dir1 = hashCode & 0xf; // 一级 目录 1
		int dir2 = (hashCode >> 4) & 0xf; // 二级目录 4

		// WEB-INF/upload/1/4/xx.txt
		// d://aa//bb//cc/upload/1/4
		String savePath = realPath + "/" + dir1 + "/" + dir2;

		File file = new File(savePath);

		if (!file.exists()) {

			file.mkdirs();
		}

		return savePath;
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

原文链接: 文件上传细节详解 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( http://gyarmy.com/post-90.html )

发表评论

0则评论给“文件上传细节详解”