web 中常用的兩種上傳檔案的方法總結
這裡我們來總結整理一下常用的兩種檔案上傳方式以及要注意的東西:
1、springmvc .MultipartFile 的上傳方式。
2、org.apache.commons.fileupload 使用apache的fileuoload 來實現
當我們使用springmvc 的MultipartFile 時我們要在spring的配置檔案中新增如下的配置檔案:
(1)、bean的引入以及編碼和上傳檔案大小兩個屬性的設定
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8" /> <property name="maxUploadSize" value="2000000000" /> </bean>
(2)、控制層的程式碼:
public void upload2(HttpServletRequest request) { // 轉型為MultipartHttpRequest try { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; List<MultipartFile> fileList = multipartRequest.getFiles("file"); for (MultipartFile mf : fileList) { if(!mf.isEmpty()){ } } } catch (Exception e) { e.printStackTrace(); } }
這樣就簡單的獲取了上傳檔案,其實我們上傳的檔案就是一個MultipartFile 物件,獲取了物件後我們就可以獲取檔名以及輸入流。
(3)、控制層的第二種方式:
public String upload(HttpServletRequest request, @RequestParam(value = "file") MultipartFile[] files) { try { for (MultipartFile mf : files) { if(!mf.isEmpty()){ } } } catch (Exception e) { e.printStackTrace(); } return "upload"; }
(2)、(3)、不管哪種,其實都是一樣的原理,都是將上傳檔案轉化為了物件。
這裡springMVC 都為我們封裝好成自己的檔案物件了,轉換的過程就在我們所配置的CommonsMultipartResolver這個轉換器裡面下面再來看看它的原始碼
看到這個你應該明白了,如果你配置了multipartResolver 這個bean 則程式會自動呼叫fileUpload 來解析request ,在控制層獲取的request已經是被解析過的,所以不用在手動去呼叫fileUpload 的相關方法來解析這個request。但注意,如果在spring的配置檔案中沒有配置這個bean的話,則我們自己要在controller層呼叫fileUpload 的相關方法來解析request 。ok這裡說了第一種使用springmvc 的MultipartFile ,但是第二種和第一種其實是一樣的,第一種解析的過程由spring替我們幹了,我們只需要獲取資料就ok而第二種方式就是在spring 的配置檔案中不配置bean 這樣在控制層中我們只能自己去解析請求。
所以簡單的來說其實就是一種技術的兩種使用方式,第一種是配置在了spring 容器中而第二種就是不配置在spring容器中而是自己去解析請求資訊。
注意:剛開始學習的時候,你肯能不瞭解而出現了獲取不到資料的這種情況,那就是在你不知不覺中解析了兩次request所以你獲取不到你想要的資料,那怎麼處理那其實很簡單,具體看下面:
1、不在spring的配置檔案中配置,則需要你在控制層呼叫fileupload 的方法進行解析:
@RequestMapping(value="/upload.do")
@SuppressWarnings("unchecked")
public void upload(HttpServletRequest request,HttpServletResponse response) throws IOException, FileUploadException{
System.out.println("檔案存放目錄、臨時檔案目錄準備完畢 ...");
System.out.println("filePath-->:"+filePath);
System.out.println("tempPath-->:"+tempPath);
response.setContentType("text/plain;charset=utf-8");
PrintWriter pw = response.getWriter();
// 磁碟檔案工廠,建立快取檔案
DiskFileItemFactory diskFactory = new DiskFileItemFactory();
// threshold 極限、臨界值,即磁碟快取大小設定
diskFactory.setSizeThreshold(10*4 * 1024);
// repository 貯藏室,即臨時檔案目錄 ,設定檔案的快取路徑
diskFactory.setRepository(new File(tempPath));
ServletFileUpload upload = new ServletFileUpload(diskFactory);
// 設定允許上傳的最大檔案大小 ,如果是-1表示沒有限制
upload.setSizeMax(10 * 1024 * 1024);
//解決上傳的檔名亂碼
upload.setHeaderEncoding("UTF-8");
// 3、判斷使用者的表單提交方式是不是multipart/form-data,這也是我們在form中設定的那個屬性的值 是不是……
boolean bb = upload.isMultipartContent(request);
if (!bb) {
return ;
}
// 解析HTTP請求訊息頭 ,也就是呼叫方法解析提交的內容並將其組裝成一個個的FileItem物件
// 而其中上傳的一個檔案就是一個FileItem物件
List<FileItem> fileItems = upload.parseRequest(request);
try {
Iterator<FileItem> iter = fileItems.iterator();
while(iter.hasNext())
{
FileItem item = (FileItem)iter.next();
//按照給定的編碼格式獲取上傳檔案內容
String fieldValue = item.getString("UTF-8");
//獲取標籤名稱
String tagName = item.getFieldName();
//獲取檔名稱
String fileName= item.getName();
//上傳檔案輸入流,也就是整個上傳檔案的流
InputStream input = item.getInputStream();
System.out.println("tagName--->:"+tagName +"fileName--->"+fileName );
//判斷這個FileItem是不是表單屬性(他能判斷是上傳的檔案還是表單屬性)
if(item.isFormField())
{
System.out.println("處理表單內容 ...");
processFormField(item, pw);
}else{
System.out.println("處理上傳的檔案 ...");
processUploadFile(item, pw);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
pw.close();
}
}
/**
* 處理表單內容
* @param item
* @param pw
* @throws Exception
*/
private void processFormField(FileItem item, PrintWriter pw)
throws Exception
{
String tagName = item.getFieldName();
String fileName = item.getString("utf-8");
pw.println(tagName + " : " + fileName + "\r\n");
}
/**
* 處理上傳的檔案
* @param item
* @param pw
* @throws Exception
*/
private void processUploadFile(FileItem item, PrintWriter pw)
throws Exception
{
//檔名稱
String filename = item.getName();
System.out.println("完整的檔名:" + filename);
//上傳檔案大小(byte)
long fileSize = item.getSize();
if("".equals(filename) && fileSize == 0)
{
System.out.println("檔名為空 ...");
return;
}
System.out.println("filePath:-->"+filePath);
System.out.println("filename:--->"+filename);
//建立儲存檔案路徑
File uploadFile = new File(filePath +File.separator + filename);
if(!uploadFile.getParentFile().exists()){
uploadFile.getParentFile().mkdirs();
}
uploadFile.createNewFile();
//將上傳上來的檔案內容寫到指定的檔案
item.write(uploadFile);
//向瀏覽器列印
pw.println(filename + " 檔案儲存完畢 ...");
pw.println("檔案大小為 :" + fileSize + "\r\n");
}
2、在spring的配置檔案中配置了這個bean 則不在需要我們自己呼叫一個fileupload 的方法再去解析一次,而是直接使用:
/**
* spring mvc MultipartFile 多檔案上傳
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value="/upload1.do")
public void upload1(HttpServletRequest request,HttpServletResponse response) throws IOException{
//建立一個通用的多部分解析器
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
//判斷使用者的表單提交方式是不是multipart/form-data,這也是我們在form中設定的那個屬性的值 是不是……
if(multipartResolver.isMultipart(request)){
//判斷 request 是否有檔案上傳,即多部分請求
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
//獲取所有上傳檔案的名稱是input標籤中的名稱
Iterator<String> iter = multipartRequest.getFileNames();
while(iter.hasNext()){
String name = iter.next();
//按照檔名稱獲取這個上傳檔案,上傳檔案被轉化為MultipartFile 物件
MultipartFile file= multipartRequest.getFile(name);
//獲取檔名,這裡的fname也是input標籤中的name而不是檔名
String fname= file.getName();
//這裡獲取到的才是真真的檔名稱 比如test.txt等這樣的名稱。
String myfname= file.getOriginalFilename();
//獲取輸入流
InputStream input = file.getInputStream();
System.out.println("fname: "+fname +" name: "+name +" myfname:"+myfname);
}
//這的getFiles("file")就是獲取多個input標籤名稱為file的檔案。
List<MultipartFile> fileList = multipartRequest.getFiles("file");
for(MultipartFile file:fileList){
System.out.println("----fileList size:"+fileList.size());
//獲取input標籤中的名稱
String name= file.getName();
//這裡獲取到的才是真真的檔名稱 比如test.txt等這樣的名稱。
String myfname= file.getOriginalFilename();
//獲取這個檔案的輸入流
InputStream input = file.getInputStream();
System.out.println("name"+name +"myfname:"+myfname);
}
}
PrintWriter p= response.getWriter();
p.write("ok!!!");
}
ok到這裡兩種使用方法也說完了,也明白了SpringMVC中servletFileUpload.parseRequest(request)解析為空獲取不到資料的問題,獲取不到是因為我們解析了兩次,所以我們要知道,如果你在spring的配置檔案中配置了,值按照2 這種方式直接使用,而如果沒有配置則需要我們按照1 中的方式先去解析request 在使用!