javaweb基础之----- Servlet中文件的上传

一、文件上传的三要素

1、提供form表单,method必须是post

2、form表单的enctype必须是multipart/form-data

3、提供input type=“file” 

二、enctype 的取值

1、application/x-www-form-urlencoded 普通表单方式

服务端使用request.getParameter("name");等方法可以获取普通字段的值

2、multipart/form-data 文件上传方式

    服务端使用request.getParameter("name");等方法不可以获取普通字段的值

因为getParameter(String name)方法,获取的是字符流,但文件上传表单已经不再是字符内容,而是字节内容

需要使用第三方的插件:file-upload      链接:https://pan.baidu.com/s/1z02xCCZT7HpGpYk_y8Ur5w 密码:pmg3

fileupload:是由Apache 的commons组件提供的。主要工作是帮助我们解析request.getInputStream()

三、实现文件的上传

1、导入两个jar包:  commons-fileupload-1.2.2         commons-io-2.2

2、fileUpload的核心类

  •     DiskFileItemFactory  创建工厂对象
  •    ServletFileUpload 使用工厂  创建解析器对象
  •   FileItem 使用解析器来解析request对象   : 可以获取普通标签和上传文件的标签

3、方法 

  • boolean isFormField() :判断当前的表单标签是否是普通标签  true 普通标签  false  文件上传标签
  • String getFieldName() 获取 标签名
  • String getString("编码集" );  获取值并解决乱码
  • String getName();  获取上传域中添加的文件路径(绝对路径)
  • void write(File) 把上传的文件保存在指定的文件中

文件上传时需要注意的问题:

A、限制文件的大小

  •   为了项目的安全性考虑,设置文件的大小限制
  •   设置单个的文件大小:SerlvetFileUpload.setFileSizeMax()
  •   设置文件上传的总大小:ServletFIleUpload.setSizeMax()

B、设置临时文件

  •        DiskFileFactory.setRepository("设置临时文件的位置"):
  •        如果上传的文件比较大,会产生一个临时文件,当文件上传成功,临时文件会被清理
  •      注意:不要设置在系统盘,一般情况下,系统盘都有保护
  •      临时文件:相当于缓存,缓存的大小是10kb,如果上传的文件大的话,就会出现临时文件,缓存数据

C、判断表单是否支持文件上传

  • 判断表单是否设置了 enctype
  • entype必须是multipart/form-data
  • ServletFileUpload isMultipartContent(request)   支持true,不支持false

D、避免出现重名覆盖

  •      文件名重组加上UUID.randomUUID()

E、避免同一个文件夹中文件过多  :打散目录

  • 1、按照日期进行打散存储,当前日期/fileName
  • 2、按照文件名 获取哈希值转成十六进制,创建文件夹     Integer.toHexString(hashcode);

F、解决中文乱码问题

  • 1、解决上传框中的乱码   ServletFileUpload setHeaderEncoding("编码集")
  • 2、解决普通文本框的乱码   FileItem   getString("编码集")

G、截取文件名方式

  • 1、第一种:fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
  • 2、第二种:fileName = FilenameUtils.getName(fileName);

   H.文件存储路径映射

  •                将文件存储在服务器硬盘上的绝对路径 无法通过浏览器访问?
  •             在tomcat/conf/service.xml文件中<Host>标签添加一个
  •             <Context docBase="硬盘绝对路径" path="/访问地址" reloadable="true"/>

4、重要的代码:

upload.jsp

<form action="uploadServlet" method="post" enctype="multipart/form-data">
文件名:<input type="text" name="filename"/><br/>
文件描述:<input type="text" name="desc"><br/>
文件:<input type="file" name="upload"><br/>
<input type="submit" value="提交"><br/>
</form>

UploadServlet.java

@WebServlet("/uploadServlet")
public class UploadServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//C.判断表单是否支持文件上传
		boolean flag = ServletFileUpload.isMultipartContent(req);
		if(!flag){
			throw new RuntimeException("你的表单不支持文件上传");
		}
		//1.创建工厂类对象
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//B.设置临时文件 相当于是缓冲区
		factory.setRepository(new File("d:\\"));
		//2.创建解析器
		ServletFileUpload upload = new ServletFileUpload(factory);
		//F.解决中文乱码问题(上传框)
		upload.setHeaderEncoding("utf-8");
		//3.获取FileItem集合 解析请求 获取提交的表单元素的集合 包括普通标签 和 上传框
		try {
			//A限制文件大小
//			upload.setFileSizeMax(1024*1024*2);//2m 设置单文件大小
//			upload.setSizeMax(1024*1024*10);//10m 设置总大小
			List<FileItem> items = upload.parseRequest(req);
			for(FileItem item : items){
				if(item.isFormField()){//判断表单元素 是普通 还是上传
					//普通标签
					processFormFile(item);
				}else{
					//上传标签
					processUploadFile(item);
				}
			}
		} catch(FileUploadBase.SizeLimitExceededException e){
			System.out.println("文件过大 单文件不能超过2m ");
			//作业1 当文件过大 将提示信息 显示在 upload.jsp上
			
		}catch (FileUploadException e) {
			e.printStackTrace();
		}
	}
	//处理普通标签
	private void processFormFile(FileItem item) {
		// 获取标签名
		String name = item.getFieldName();
		//获取值
		//F.解决普通标签中文乱码
		String value ="";
		try {
			value = item.getString("utf-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(name+"::"+value);
	}
	//处理上传标签
	private void processUploadFile(FileItem item) {
		//1.在服务器上创建文件夹 来存储要上传的文件
		String uploadPath = "D:\\web09_upload\\files\\";
		//2.判断路径是否存在 如果不存在 就创建
		File storePath = new File(uploadPath);
		if(!storePath.exists()){
			storePath.mkdirs();
		}
		//3.获取上传框中的文件
		String fileName = item.getName();
		//G.判断上传字段 是否有值
		if(fileName!=null){
			//D.避免文件名重复 覆盖现象 加上 UUID
			fileName = UUID.randomUUID()+"_"+fileName;
			//4.截取文件名 第一种
			//fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
			//4.截取文件名 第二种 
			fileName = FilenameUtils.getName(fileName);
			//E.打散目录 第一种方式 按照日期打散
			//storePath = makeChildDir(storePath);
			//E.打散目录 第二种方式 按照文件名 获取哈希值 转成16进制 打散目录
			storePath = makeChildDir(storePath,fileName);
			//5.将文件保存入文件夹
			File file = new File(storePath, fileName);
			try {
				item.write(file);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}	
	}
	//方式1
	private File makeChildDir(File storePath) {
		// 按照日期创建文件夹
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String dateDir = sdf.format(new Date());
		File file = new File(storePath, dateDir);
		if(!file.exists()){
			file.mkdirs();
		}
		return file;
	}
	//方式2
	private File makeChildDir(File storePath, String fileName) {
		// 获取哈希码
		int hashCode = fileName.hashCode();
		// 转成16进制
		String hex = Integer.toHexString(hashCode);
		String s = hex.charAt(0)+File.separator+hex.charAt(1); // 7a --> 7/a
		File file = new File(storePath, s);
		if(!file.exists()){
			file.mkdirs();
		}
		return file;
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doGet(req, resp);
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42496678/article/details/82291227