文件上传 fileUpload

原因

1. 上传文件,方法一定要用post
2. 上传文件仅上传文件名,不上传文件的内容,
   需要设置enctype属性 enctype="multipart/form-data",这时上传的文件中还包含一些不属于文件的东西,需要分割
3. 这个时候如果还上传了普通的表单数据,会和文件资源一起被保存到文件中
4. request.getInputStream()获得是整个请求体的内容 ,需要将不属于文件的内容分出去
	此时,request获取请求参数的API也不能用了,即request.getPramaer(name)不可用
5. 要使用专门的文件上传组件

文件上传组件

依赖包

	Commons-fileupload和commons-io

实现步骤

	1、创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录
		
		//工厂约束
			public DiskFileItemFactory(int sizeThreshold, java.io.File repository) //构造函数
			public void setSizeThreshold(int sizeThreshold) //设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。
			public void setRepository(java.io.File repository) //指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").
				factory.setSizeThreshold(yourMaxMemorySize);
				factory.setRepository(yourTempDirectory);
				
	2、使用DiskFileItemFactory 对象创建ServletFileUpload对象,并设置上传文件的大小限制。
			List parseRequest(HttpServletRequest request)//解析request对象,并把表单中的每一个输入项包装成一个fileItem 对象,并返回一个保存了所有FileItem的list集合。 
			
			boolean isMultipartContent(HttpServletRequest request) //判断上传表单是否为multipart/form-data类型
			
		//上传文件大小约束
			setFileSizeMax(long fileSizeMax)//设置单个上传文件的最大值bytes
			setSizeMax(long sizeMax) //设置上传文件总量的最大值(多个文件同时上传时文件最大值的总和)
			setHeaderEncoding(java.lang.String encoding)//设置编码格式,解决上传文件名乱码问题

		
	3、调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。
			boolean  isFormField() //判断FileItem是一个文件上传对象还是普通表单对象
			1.如果判断是一个普通表单对象
				String   getFieldName()  //获得普通表单对象的name属性
				String  getString(String encoding) //获得普通表单对象的value属性
			2.如果判断是一个文件上传对象
				String  getName() //获得上传文件的文件名(有些浏览器会携带客户端路径)
				InputStream getInputStream()  //获得上传文件的输入流
				delete()  //在关闭FileItem输入流后,删除临时文件

	4、对list进行迭代,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件
		True 为普通表单字段,则调用getFieldName、getString方法得到字段名和字段值
		False 为上传文件,则调用getInputStream方法得到数据输入流,从而读取上传数据。
	
	//检查我们是否有文件上传请求
	boolean isMultipart = ServletFileUpload.isMultipartContent(request);

示例:

		1.创建一个工厂
			DiskFileItemFactory factory = new DiskFileItemFactory();
		2.配置存储文件的地址库
			ServletContext servletContext = this.getServletConfig().getServletContext();
			File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
			factory.setRepository(repository);
		3.创建ServletFileUpload对象,用于解析request
			ServletFileUpload upload = new ServletFileUpload(factory);
		4.解析request
			List<FileItem> items = upload.parseRequest(request);
		5.遍历上传的文件
			Iterator<FileItem> iter = items.iterator();
			while(iter.hasNext()){
				FileItem item = iter.next();
				if(item.isFormField){
					processFormField(item);//处理表单
				}else{
					processUploadFile(item);//处理上传文件
				}
			}
		6.处理表单
			String name = item.getFieldName();//获取表单key
			String value = item.getString("utf-8");//获取表单的值,可加参数解决表单数据中文乱码问题
		7.处理文件上传
			String fieldName = item.getFieldName();
			String fileName = item.getName();
			contentType = item.getContentType();
			boolean isInMemory = item.isInMemory();
			long sizeInBytes = item.getSize();
		8.将文件存入磁盘
		
		
			String upload = getServletContext().getRealPath("upload");
			File file = new File(upload + "/" + fileName);
			item.write(file);

细节

		1.上传文件重名问题
			//文件名称需要做一个处理,保证每一个文件不会与其他文件重名
				方式一:用户的id -_ fileName
				方式二:当前的时间戳加上一些序列数2019082411254790
				方式三:加随机数uuid
			
			String uuid = UUID.randomUUID().toString();
			fileName = uuid + "-" + fileName;
		
		2.文件数目过多
			//使用散列分散文件
			String upload = getServletContext().getRealPath("upload");
			int hashCode = fileName.hashCode();
			//int 32  16  8   1 2 3 4 a b f 3  16^8 40亿左右
			String s = Integer.toHexString(hashCode);//转成16进制,八个文件夹
			char[] chars = s.toCharArray();
			for (char aChar : chars) {
				upload = upload + "/" + aChar;
			}
			File file = new File(upload + "/" + fileName);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章