javaweb上传文件
目錄
1.簡(jiǎn)述
2.原理講解
3.代碼如下(含注釋)
3.1獲得DiskFileItemFactory對(duì)象
3.2獲得ServletFileUpload對(duì)象?
?3.3上傳文件?
3.4 doPost()
4.運(yùn)行結(jié)果
1.簡(jiǎn)述
在一個(gè)web項(xiàng)目中,用戶向工程中上傳文件是十分常見的操作,如頭像設(shè)置、背景圖片設(shè)置等。服務(wù)器在保存用戶上傳的文件的時(shí)候,需要解決以下四個(gè)問題:1.用戶上傳的文件不能直接通過在地址欄輸入url去訪問;2.用戶上傳的文件不能被覆蓋(在同一個(gè)文件夾下的同名文件會(huì)被覆蓋);3.限制上傳文件的最大值;4.可以限制上傳文件的類型,在收到上傳文件名時(shí),判斷后綴名是否合法。
這篇文章將簡(jiǎn)單講解如何在Javaweb項(xiàng)目上傳文件并解決上面提到的四個(gè)問題
2.原理講解
上傳文件的表單如圖所示
一般在處理上傳文件的時(shí)候,用流來處理,但是這樣的話需要自己實(shí)現(xiàn)網(wǎng)絡(luò)通信底層,太麻煩了,這里使用apache的commons-io組件來完成。
ServletFileUpload類負(fù)責(zé)處理上傳的文件數(shù)據(jù),并將表單中的每個(gè)輸入項(xiàng)封裝成FileItem對(duì)象。在獲取ServletFileUpload對(duì)象的時(shí)候,需要一個(gè)DiskFileItemFactory對(duì)象
通過ServletFileUpload對(duì)象獲得FileItem對(duì)象后,遍歷所有的FileItem對(duì)象,判斷每個(gè)對(duì)象只是簡(jiǎn)單的表單元素還是包含了文件,若包含了文件,將文件進(jìn)行處理保存,并轉(zhuǎn)發(fā)到上傳信息的頁面就好了。
為了避免用戶通過輸入url地址直接訪問到服務(wù)器上的文件,可以設(shè)置攔截器,這里就直接把文件存儲(chǔ)在WEB-INF目錄下了。為了防止文件覆蓋,項(xiàng)目中使用了UUID這個(gè)類來獲得一個(gè)唯一的標(biāo)識(shí)符,利用這個(gè)唯一的標(biāo)識(shí)符來存儲(chǔ)文件就不會(huì)發(fā)生覆蓋的情況了。
3.代碼如下(含注釋)
3.1獲得DiskFileItemFactory對(duì)象
public DiskFileItemFactory getDiskFileItemFactory(File tempFile){DiskFileItemFactory factory = new DiskFileItemFactory(); // 為上傳文件設(shè)置一個(gè)大小限定,當(dāng)文件超過這個(gè)大小的時(shí)候,緩存在暫存區(qū)factory.setSizeThreshold(1024*1024); //大小為1Mfactory.setRepository(tempFile); //設(shè)置暫存區(qū)return factory;}3.2獲得ServletFileUpload對(duì)象?
public ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){ServletFileUpload upload = new ServletFileUpload(factory);upload.setProgressListener(new ProgressListener() {@Override // pBytesRead:已經(jīng)讀取的文件大小 // pContentLength:文件總大小public void update(long pBytesRead, long pContentLength, int pItems) {System.out.println("總大小:"+ pContentLength + ";已上傳:" + pBytesRead);}}); // 處理亂碼問題upload.setHeaderEncoding("UTF-8"); // 設(shè)置單個(gè)文件的最大值upload.setFileSizeMax(1024*1024*10); // 設(shè)置總共能夠上傳文件的大小upload.setSizeMax(1024*1024*10);return upload;}?3.3上傳文件?
public void uploadFile(HttpServletRequest req, HttpServletResponse resp,ServletFileUpload upload, String uploadPath) throws IOException, ServletException {String msg = "文件上傳失敗";// 把前端請(qǐng)求解析,封裝成一個(gè)FileItem對(duì)象,從ServletFIleUpload對(duì)象中獲取List<FileItem> fileItems = null;try {fileItems = upload.parseRequest(req);} catch (FileUploadException e) {e.printStackTrace();}for (FileItem fileItem : fileItems) { // 當(dāng)前FileItem對(duì)象只是一個(gè)表單對(duì)象if(fileItem.isFormField()){String name = fileItem.getFieldName(); //獲得表單控件的name值String value = fileItem.getString("UTF-8");//獲得文本,處理亂碼System.out.println(name+" :"+value);}else { // 當(dāng)前FileItem包含文件 // ===========================處理文件===============================String uploadFileName = fileItem.getName();if(uploadFileName.trim().equals("") || uploadFileName==null){continue;}// 獲得上傳的文件名String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/")+1); // 獲得上傳的文件后綴String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);// 使用UUID獲得一個(gè)唯一的識(shí)別通用碼,保證文件名唯一 // 網(wǎng)絡(luò)傳輸中的東西,都需要序列化 // 實(shí)體類如果想要在多個(gè)電腦上運(yùn)行,需要進(jìn)行傳輸===》使用序列號(hào)String uuidPath = UUID.randomUUID().toString();// ==========================存放地址==========================================String readPath = uploadPath+"/"+uuidPath; // 給每個(gè)文件創(chuàng)建也給對(duì)應(yīng)的文件夾File realPathFile = new File(readPath);if(!realPathFile.exists()){realPathFile.mkdir();}// ===========================文件傳輸========================================== // 獲得文件上傳的流InputStream inputStream = fileItem.getInputStream(); // 創(chuàng)建一個(gè)文件輸出流FileOutputStream fos = new FileOutputStream(readPath+"/"+fileName); // 創(chuàng)建一個(gè)緩沖區(qū)byte[] buffer = new byte[1024*1024]; // 判斷是否讀取完畢int len = 0;while ((len=inputStream.read(buffer))>0){fos.write(buffer, 0, len);} // 關(guān)閉流fos.close();inputStream.close();}msg = "文件上傳成功";}req.setAttribute("msg", msg);req.getRequestDispatcher("info.jsp").forward(req, resp);}3.4 doPost()
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 判斷上傳的文件是普通表單還是帶文件的表單String msg = "文件上傳失敗";if(!ServletFileUpload.isMultipartContent(req)){return;}// 創(chuàng)建上傳文件的保存路徑,建議放在web-inf路徑下以保證安全,用戶無法直接訪問上傳的文件String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");File uploadFile = new File(uploadPath);if(!uploadFile.exists()){//如果文件夾不存在,則創(chuàng)建改文件夾uploadFile.mkdir();}// 緩存臨時(shí)文件 // 臨時(shí)路徑,如果文件超過了預(yù)期大小,就放到臨時(shí)文件夾下String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");File tmpFile = new File(tmpPath);if(!tmpFile.exists()){tmpFile.mkdir();}// 處理上傳的文件,一般需要通過流來獲取 // 此處使用apache的組件來實(shí)現(xiàn) commons-io/** ServletFileUpload負(fù)責(zé)處理上傳的文件數(shù)據(jù),并將表單中的每個(gè)輸入項(xiàng)封裝成fileItem對(duì)象* 在使用ServletFileUpload對(duì)象解析請(qǐng)求時(shí)需要DIskFileItemFactory對(duì)象* 所有,需要在進(jìn)行解析工作前構(gòu)造好DiskFileItemFactory對(duì)象*/// 1. 創(chuàng)建DiskFileIntemFactory對(duì)象,處理文件上傳路徑或者大小限制DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);// 2。獲取ServletFileUploadServletFileUpload upload = getServletFileUpload(factory);// 3.處理上傳文件uploadFile(req, resp,upload, uploadPath);}補(bǔ)充:通過表單上傳文件,get方法對(duì)上傳文件的大小有限制,post方法沒有限制,所以一般使用post方法。而且使用get方法的話在獲取ServletFileUpload時(shí)會(huì)出錯(cuò)。另外,表單如果包含一個(gè)文件上傳輸入的話,這個(gè)表單的enctype屬性就必須設(shè)置為multipart/form-data。
4.運(yùn)行結(jié)果
通過表單提交了文件后,可以在tomcat目錄下找到項(xiàng)目文件夾,在WEB-INF目錄下就多出了upload和temp這兩個(gè)文件夾,上傳的文件都保存在這兩個(gè)文件夾下面。
總結(jié)
以上是生活随笔為你收集整理的javaweb上传文件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python拼图游戏_Python加py
- 下一篇: 光学遥感基础总结