servlet实现文件上传

(1)导包

                 如果直接使用servlet获取上传文件的输入流,然后再解析里面的请求参数时比较麻烦的,所以一般选择采用apache的开源工具common-fileupload实现文件上传。

                由于common-fileupload是依赖于common-io的,所以还需要导入common-io这个包

            1.以maven形式

<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.3.1</version>
</dependency>
              2.直接导包 
               


(2)实现

           1.上传页面编写

<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
</head>  
<body>
    <form action="/LearnServlet/UploadHandleServlet" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="username"><br/>
        上传文件:<input type="file" name="file1"><br/>
        <input type="submit" value="提交">
    </form>
</body>
</html> 
                 只需要将input标签的type定义为file即可


           2.响应页面编写
                   为了能够显示出上传的结果

<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>消息提示</title>
  </head>
  
  <body>
        ${message}
  </body>
</html>

           3.上传servlet
                   整体代码:

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

		// 消息提示
		String message = "";

		boolean success = makeUploadDir();
		if (success) {
			// 1、判断提交上来的数据是否是上传表单的数据
			if (ServletFileUpload.isMultipartContent(request)) {
				ServletFileUpload upload = initUploadUitl();
				try {
			// 4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
					List<FileItem> list = upload.parseRequest(request);
					for (FileItem item : list) {
						if (item.isFormField()) {// 如果fileitem中封装的是普通输入项的数据,直接输出
							outputNormalData(item);
						} else {// 如果fileitem中封装的是上传文件
							String fileNameame = getFileName(item);
							if (fileNameame==null) {
								message = "文件名为空";
							}else {
								saveUploadFile(item,fileNameame);
								// 删除处理文件上传时生成的临时文件
								item.delete();
								message = "文件上传成功!";
							}
						}
					} 
				}catch (Exception e) {
					message = "文件上传失败!";
					e.printStackTrace();

				}
			} else {
				message = "表单数据不是上传文件的数据";
			}
		} else {
			message = "创建文件上传目录失败";
		}

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

                   3.1创建上传文件的保存目录

	private String savePath;
	
	private boolean makeUploadDir() {
		// 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
		savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
		File file = new File(savePath);
		// 判断上传文件的保存目录是否存在
		if (!file.exists() && !file.isDirectory()) {
			System.out.println(savePath + "目录不存在,需要创建");
			// 创建目录
			return file.mkdir();
		} else {
			return true;
		}
	}

                   3.2 初始化上传工具类

	private ServletFileUpload initUploadUitl() {
		// 使用Apache文件上传组件处理文件上传步骤:
		// 1、创建一个DiskFileItemFactory工厂
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 2、创建一个文件上传解析器
		ServletFileUpload upload = new ServletFileUpload(factory);
		// 解决上传文件名的中文乱码
		upload.setHeaderEncoding("UTF-8");

		return upload;
	}

                   3.3 普通表单字段直接输出

	private void outputNormalData(FileItem item) throws UnsupportedEncodingException {
		String name = item.getFieldName();
		// 解决普通输入项的数据的中文乱码问题
		String value = item.getString("UTF-8");
		System.out.println(name + "=" + value);
	}


                   3.4 获取文件名称

	// 注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:
	// c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
	private String getFileName(FileItem item) {
		String filename = item.getName();// 得到上传的文件名称
		System.out.println(filename);
		if (filename == null || filename.trim().equals("")) {
			return null;
		}else {
			// 处理获取到的上传文件的文件名的路径部分,只保留文件名部分
			filename = filename.substring(filename.lastIndexOf("\\") + 1);
			return filename;
		}
		
	}


                   3.5 保存上传的文件

	private void saveUploadFile(FileItem item,String fileName) throws IOException {
		// 获取item中的上传文件的输入流
		InputStream in = item.getInputStream();
		// 创建一个文件输出流
		FileOutputStream out = new FileOutputStream(
				savePath + "\\" + fileName);
		// 创建一个缓冲区
		byte buffer[] = new byte[1024];
		// 判断输入流中的数据是否已经读完的标识
		int len = 0;
		// 循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
		while ((len = in.read(buffer)) > 0) {
			// 使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath
			// + "\\" + filename)当中
			out.write(buffer, 0, len);
		}
		// 关闭输入流
		in.close();
		// 关闭输出流
		out.close();
	}

             执行上传,结果如下:

             


(3)优化

                1.限制上传文件的大小

                   需要限制单个文件的大小, 并且还可以限制文件上传总量的最大值

                   单个文件大小限制:

upload.setFileSizeMax
                   文件总量大小限制
upload.setSizeMax

                2.监听文件上传进度

                   传递一个ProgressListener即可

upload.setProgressListener(new ProgressListener(){..})

                3.设置缓冲区

                   如果文件大小超过缓冲区大小,就只能写在一个临时文件中

factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
//设置上传时生成的临时文件的保存目录
factory.setRepository(tmpFile);

               因为这里的优化只涉及到DiskFileItemFactory和ServletFileUpload,所以优化后的代码为:

	private ServletFileUpload initUploadUitl() {
		// 使用Apache文件上传组件处理文件上传步骤:
		// 1、创建一个DiskFileItemFactory工厂
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
	    factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
	    //设置上传时生成的临时文件的保存目录
	    //上传时生成的临时文件保存目录
		String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
		File tmpFile = new File(tempPath);
		if (!tmpFile.exists()) {
			// 创建临时目录
			tmpFile.mkdir();
		}
	    factory.setRepository(tmpFile);
	    
		// 2、创建一个文件上传解析器
		ServletFileUpload upload = new ServletFileUpload(factory);
		//监听文件上传进度
		upload.setProgressListener(new ProgressListener(){
		  public void update(long pBytesRead, long pContentLength, int arg2) {
		              System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
		              /**
		                * 文件大小为:14608,当前已处理:4096
		                                               文件大小为:14608,当前已处理:7367
		                                               文件大小为:14608,当前已处理:11419
		                                              文件大小为:14608,当前已处理:14608
		                */
		               }
		 });
		// 解决上传文件名的中文乱码
		upload.setHeaderEncoding("UTF-8");
		//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
		upload.setFileSizeMax(1024*1024);
		//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
		upload.setSizeMax(1024*1024*10);

		return upload;
	}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值