利用Apache的FileUpload類庫實現檔案上傳
一、Web資源
FileUpload首頁:http://commons.apache.org/fileupload/
Commons IO類庫:http://commons.apache.org/io/ ,FileUpload需要用於該類庫,
所以你確保該類庫在您的classpath中,否則會出現異常。
二、相關類與介面
1、DiskFileItemFactory 類
實現了FileItemFactory,根據名字翻譯就是”檔案項工廠”,實際作用是定義檔案傳過程中檔案佔用的記憶體,及超過佔用記憶體時臨時檔案的儲存地點,主要方法如下:
void setSizeThreshold(int sizeThreshold)
//以byte為單位設定檔案使用多少記憶體量後,將檔案存入臨時儲存。
void setRepository(java.io.File repository) //設定臨時檔案的儲存路徑
2、ServletFileUpload類
處理同一HTML檔案中多檔案上傳的類,繼承自FileUpload,主要方法如下:
Java代碼
1. static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request)
//判斷用戶端請求是否為POST,並且enctype屬性是否是“multipart/form-data"
2. public java.util.List parseRequest(javax.servlet.http.HttpServletRequest request)
throws FileUploadException //讀入“multipart/form-data"資料流並得到表單項列表。
3.void setSizeMax(long sizeMax) //設定允許上傳檔案的最大大小
在得到上傳檔案之前,首先要判斷用戶端<form>標記的enctype屬性是否是“multipart/form-data",可使用org.apache.commons.fileupload.servlet.ServletFileUpload類中的isMultipartContent()方法進行進行判斷
3、FileItem介面
根據名字翻譯就是檔案項,代表所提交表單中的一個控制項,ServletFileUpload中的parseRequest()檔案返回整個表單的所有FileItem項的列表。
1 boolean isFormField() //判斷該表單項是否是檔案項,還是普通表單項。
2 String getFieldName() //如果不是檔案項,返回對應表單項的表單名稱。
3 String getString() //如果不是檔案項,以預設編碼返回該項的內容。
4 String getString(String encoding) //以指定編碼返回該項內容。
5 long getSize() //以byte為單位返回該項大小
6 String getName() //如果是檔案項,該方法返迴文件名,檔案名稱取決於用戶端瀏覽器
7 void write(java.io.File file) //如果是檔案項,將該檔案寫入對應的檔案中
8 java.io.InputStream getInputStream()
9 java.io.OutputStream getOutputStream()
三、使用方法
1、首先將FileUpload包和其相關的Commons IO包存放在Web應用的WEB-INF/lib中。
2、一個簡單的樣本,運行檔案並儲存到D盤某個目錄下。
Java代碼
1 //檔案上傳樣本程式
2 //判斷表單是否是 enctype="multipart/form-data"
3 if(ServletFileUpload.isMultipartContent(request)){
4
5 DiskFileItemFactory dfif = new DiskFileItemFactory();
6 dfif.setSizeThreshold(5 * 1024 * 1024); //設定使用記憶體超過5M時,將產生臨時檔案並儲存於臨時目錄中。
7 dfif.setRepository(new File("c://temp")); //設定儲存臨時檔案的目錄。
8
9 ServletFileUpload fileupload = new ServletFileUpload(dfif);
10 fileupload.setSizeMax(50 * 1024 * 1024); //設定最大允許上傳50M的檔案。
11
12 List<FileItem> files = fileupload.parseRequest(request);
13 for(FileItem f:files){
14 if(f.isFormField()){ //如果該項是表單項,不是檔案上傳項
15 out.print(f.getFieldName());
16 out.print(f.getString("UTF-8")); //因為Web使用是的UTF-8編碼,所以用戶端返回的也是UTF-8的編碼。
17 }else{
18 String filename = f.getName();
19 filename = filename.substring(filename.lastIndexOf("."));
20 f.write(new File("d://upfile//" + (int)(Math.random()*10000000) + filename)); //別學我,偷懶行為
21 }
22 }
23 }else{
24 out.print("你所提交的表單有錯誤!");
25 }
一個JSP中使用的例子代碼
<%@ page contentType="text/html;charset=gbk" import="java.io.*,java.util.*" %>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.fileupload.servlet.*"%>
<%@ page import="org.apache.commons.fileupload.disk.*"%>
<%
if(ServletFileUpload.isMultipartContent(request)){
DiskFileItemFactory dfif = new DiskFileItemFactory();
dfif.setSizeThreshold(5 * 1024 * 1024); //設定使用記憶體超過5M時,將產生臨時檔案並儲存於臨時目錄中。
dfif.setRepository(new File("c://temp")); //設定儲存臨時檔案的目錄。
ServletFileUpload fileupload = new ServletFileUpload(dfif);
fileupload.setSizeMax(50 * 1024 * 1024); //設定最大允許上傳50M的檔案。
List files = fileupload.parseRequest(request);
Iterator i = files.iterator();
while(i.hasNext()){
FileItem f=(FileItem)i.next();
if(f.isFormField()){ //如果該項是表單項,不是檔案上傳項
可以用getString方法擷取其它內容,再轉換。
out.print(f.getFieldName());
out.print(f.getString("gbk"));
}else{
String filename = f.getName();
filename = filename.substring(filename.lastIndexOf("."));
f.write(new File("d://" + (int)(Math.random()*10000000) + filename)); //別學我,偷懶行為
}
}
}else{
out.print("你所提交的表單有錯誤!");
}
%>
檔案下載,一般是點擊串連下載的,因此可以把一下內容寫在Servlet中的doGet方法裡面。
File f = new File(savePath+fileName);
if(f==null || f.length()==0) {
response.sendRedirect(request.getContextPath()+"/filenotfound.jsp"); //檔案找不到
} else {
OutputStream out = response.getOutputStream();
response.setContentType("application/x-download");
response.setHeader( "Content-disposition", "attachment;filename= "+fileName);
response.setContentLength((int)f.length());
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(f);
int n=0;
while((n=fis.read(buffer))!=-1) {
out.write(buffer, 0, n);
out.flush();
}
out.close();
fis.close();
}