apache文件上传组件

1 获取上传组件

使用Apache Commons Fileupload 文件上传组件需要两个类库文件:

1) commons-fileupload-1.2.2.jar

2) commons-io-1.4.jar

第一步:下载commons-fileupload-1.2.2.jar

在浏览器中输入http://commons.apache.org/fileupload/ 打开Apache Commons Fileupload 文件上传组件主页面,在 Downloading 栏目中点击任意一个版本号后面的“here”超级链接,可以打开当前最新版本的 Apache Commons Fileupload 文件上传组件下载页面,(2010-08-28为止的可下载最新版本是1.2.2版)。也可以直接输入http://commons.apache.org/fileupload/download_fileupload.cgi 打开最新版本下载页面。

apache文件上传组件_第1张图片

apache文件上传组件_第2张图片

在当前最新版本的下载页面,提供二进制可执行版本(Binares)和源程序版本(Source)两种文件的下载,每一种文件都有两种压缩格式:

1) .zip,适用windows 操作系统

2) .tar.gz,适用 linux 和 unix 操作系统

我们这里选择下载 commons-fileupload-1.3.3-bin.zip 文件。解压后得到如下目录结构:

commons-fileupload-1.3.3 (根目录)

----- commons-fileupload-1.3.3.jar (我们要用的二进制类库)

-----site (包括Apache Commons Fileupload 组件站点所有页面文件)

    ----- apidocs API文档目录,API文档链接可以在下面的首页中找到,也可以直接打开此目录,点击index.html打开API文档)

    ----- index.html(站点首页)

第二步:下载commons-io-1.4.jar

在浏览器中输入http://commons.apache.org/io/ 打开 Apache Commons IO 的主页,点击左侧菜单选项中的 Download 超级链接,打开当前最新版本下载页面(http://commons.apache.org/io/download_io.cgi),选择下载 commons-io-1.4-bin.zip 文件,解压缩在根目录中即可得到 commons-io-1.4.jar 。

到这里,我们就准备好了文件上传所需要的需要类库文件了。

一般在用Servlet处理表单元素时,表单元素都是一些简单的文本,Servlet很容易用Request.getParameter()就可以处理。但是当表单不止包含一些简单的文本,比如有上传文件域时,Servlet直接从HttpServletRequest对象中解析出复合表单的每一个子部分仍然是一项非常复杂的工作.

用户在客户端提交请求的方式:

有两种方式的POST方式请求:
  1)Content-Type的值为:application/x-www-form-urlencoded
  该方式提交普通表单组件,对应file组件只提交文件名----默认
  2)Content-Type的值为:multipart/form-date
  改方式可以提交帮普通表单组件和file组件,对于file组件不仅提交文件名,还提交文件内容数据流,
  如果表单中包含file组件,必须使用该方式提交,否则不会上传文件内容数据流

文件:
文件说明:
upload

package cn.hncu.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
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.FileItemFactory;
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;
import org.apache.commons.io.FileUtils;

public class UploadServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//防止用户在地址栏,以get方式提交请求。
		response.setContentType("text/html;charset=utf-8");
		PrintWriter pw = response.getWriter();
		pw.println("文件上传出来不支持get方式提交");
		pw.close();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		request.setCharacterEncoding("utf-8");  //只对上传的文件名有效,对普通表单的编码无效
		//防黑2:防止用户以POST1的方式请求
		//法1:手动利用底层原理来实现
//		String type=request.getContentType();
//		if(!type.contains("multipart/form-date")){
//			out.println("文件上传不支持POST1方式提交");
//		}
		//法2:用apache文件上传工具提供的功能来实现
		
		
		//获取src下的目录--ClassLoader   获取WebRoot下的目录---ServletContext
		String path=getServletContext().getRealPath("/uploads");
		
		File dir=new File("e:/a");			//临时文件存放目录
		//创建一个文件上传句柄---可以对factory进行设置属性
		FileItemFactory factory=new DiskFileItemFactory(1024*8,dir);	//设置缓存的大小和位置
		/**
		 *   org.apache.commons.fileupload.servlet.ServletFileUpload类是
		 *   Apache文件上传组件处理文件上传的核心高级类
		 *   (所谓高级就是不需要管底层实现,暴露给用户的简单易用的接口)。
		 */
		ServletFileUpload upload=new ServletFileUpload(factory);	//根据参数指定的FileItemFactory对象来创建
		upload.setFileSizeMax(124*1024*5);	//设置每个文件最大为5M
		upload.setSizeMax(1024*1024*8);		//设置全部文件容量为8M
		
		//进度监听
		upload.setProgressListener(new ProgressListener() {
			/**
			 * 1.pBytesRead 已经接收了多少字节
			 * 2.pContentLength 总共多少字节
			 * 3.pItems 第几个文件(序号从1开始)
			 */
			@Override
			public void update(long pBytesRead, long pContentLength, int pItems) {
				double d=pBytesRead*100/pContentLength;		//得出的是百分数形式的进度值
				//实战时,要吧d值存入到session--表示一个用户,以让前端进度条的Ajax来读取
				System.out.println(d+"%");
			}
		});
		
		FileItem fi=null;
		
		//利用upload工具吧request中的数据解析出来,结果为List
		try {
			List list=upload.parseRequest(request);
			for(FileItem fileItem:list){
				fi=fileItem;
				if(fileItem.isFormField()){//普通表单组件
//					System.out.println("普通表单组件"+fileItem.getName());
					//解决普通表单组件的乱码问题
					String desc=fileItem.getString("utf-8"); //以指定编码来接收desc编辑框上传的参数
//					String desc=fileItem.getString();
					System.out.println("desc:"+desc);
				}else{//file组件
					String fileName=fileItem.getName();
					System.out.println("file表单组件:"+fileName);		//这里是返回file组件提交的文件名
					
					//由于服务器磁盘中存储的资源文件名不能包含中文,
					//因此要把文件名特殊处理一下(用UUid来代替),
					//同时我们在引入“打散目录技术”
					String ext=fileName.substring(fileName.lastIndexOf("."));
					String uuid=UUID.randomUUID().toString().replace("-", "");
					fileName=uuid+ext;
					/**
					 * 引入“打散目录技术”:
					 */
					String dir1=Integer.toHexString(fileName.hashCode() & 0xf);
					String dir2=Integer.toHexString((fileName.hashCode() & 0xf0)>>4);
					fileName=dir1+"/"+dir2+"/"+fileName;
					
					InputStream in = fileItem.getInputStream();			//上传文件的输入流
					//可以手动写代码进行流拷贝
					//这里使用appache的工具,更加方便
					FileUtils.copyInputStreamToFile(in, new File(path+"/"+fileName));
//					File file=new File(path+"/"+fileName);
//					File dirFile=file.getParentFile();
//					if(!dirFile.exists()){
//						dirFile.mkdir();
//					}
//					fileItem.write(file);
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			fi.delete();	//删除临时文件
		}
	}
}

你可能感兴趣的:(servlet)