文件上傳 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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章