转 [JAVA] 使用 common-fileupload 实现文件上传
就在前段時間,還在苦于找到不到合適的上傳組件,雖然很早就知道了 common-fileupload,但當時卻因為沒有找到如何獲取表單參數的方法而使用 jspSmartUpload,歷盡艱辛終于找到了它的 jar,可是使用后才發現此東西對中文參數支持奇差,甚至需要修改源代碼才能解決問題,可是jspSmartUpload并不是開源的項目,而且開發團隊也不再對它進行更新,連官方網站都關門大吉了,情急之下使用JadClipse 反編譯了它的jar包,原以為問題算是得到解決了,誰知道后來卻發現獲取到的參數經常出現部分中文亂碼,而且還不是固定的漢字出現亂碼,仔細研究加Google后才找出了規律,原來是奇數字數的中文會出現亂碼,而偶數字數的則正常,閱讀了源代碼,終于還是沒耐心閱讀下去,而且看到網上還有評論說該組件有內存泄露的問題,于是才下定決定搞定common-fileupload。
于是從 http://jakarta.apache.org/commons/fileupload/ 下載到了最新版的 FileUpload 1.2,閱讀了部分文檔跟例子,終于找到了獲取表單中參數的方法并對該組件做了進一點封裝,使其更容易使用,并支持單文件上傳和多文件上傳兩種方式,首先定義一個基類放置公共屬性:
FileUploadBase.java
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
publicabstractclass FileUploadBase {
protected Map<String, String> parameters =new HashMap<String, String>();// 保存普通form表單域
protected String encoding ="utf-8"; // 字符編碼,當讀取上傳表單的各部分時會用到該encoding
protected UploadFileFilter filter =null; // 文件過濾器, 默認為NULL 不過濾
/** *//**
* The directory in which uploaded files will be stored, if stored on disk.
*/
protectedint sizeThreshold = DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD;
/** *//**
*
* The maximum size permitted for the complete request, as opposed to
*
* {@link #fileSizeMax}. A value of -1 indicates no maximum.
*
*/
protectedlong sizeMax =-1;
/** *//**
* The directory in which uploaded files will be stored, if stored on disk.
*/
protected File repository;
public String getParameter(String key) {
return parameters.get(key);
}
public String getEncoding() {
return encoding;
}
publicvoid setEncoding(String encoding) {
this.encoding = encoding;
}
/** *//**
* 獲取上傳文件最大的大小,單位為Byte(字節),為-1時表示無限制
* @return
*/
publiclong getSizeMax() {
return sizeMax;
}
/** *//**
* 設置上傳文件最大的大小,單位為Byte(字節),為-1時表示無限制
* @param sizeMax
*/
publicvoid setSizeMax(long sizeMax) {
this.sizeMax = sizeMax;
}
publicint getSizeThreshold() {
return sizeThreshold;
}
publicvoid setSizeThreshold(int sizeThreshold) {
this.sizeThreshold = sizeThreshold;
}
/** *//**
* Returns the directory used to temporarily store files that are larger
* than the configured size threshold.
*
* @return The directory in which temporary files will be located.
*
* @see #setRepository(java.io.File)
*
*/
public File getRepository() {
return repository;
}
/** *//**
* Sets the directory used to temporarily store files that are larger than
* the configured size threshold.
*
* @param repository
* The directory in which temporary files will be located.
*
* @see #getRepository()
*
*/
publicvoid setRepository(File repository) {
this.repository = repository;
}
/** *//**
* 獲取參數列表
* @return
*/
public Map<String, String> getParameters() {
return parameters;
}
/** *//**
* 獲取過濾器
* @return
*/
public UploadFileFilter getFilter() {
return filter;
}
/** *//**
* 設置文件過濾器,不符合過濾器規則的將不被上傳
* @param filter
*/
publicvoid setFilter(UploadFileFilter filter) {
this.filter = filter;
}
/** *//**
* 驗證文件是否有效
* @param item
* @return
*/
protectedboolean isValidFile(FileItem item){
return item ==null|| item.getName() ==""|| item.getSize() ==0|| (filter !=null&&!filter.accept(item.getName())) ?false : true;
}
}
支持單文件上傳的 SingleFileUpload 類:
SingleFileUpload.java
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
publicclass SingleFileUpload extends FileUploadBase {
private FileItem fileItem;
/** *//**
*
* @param request
* @throws UnsupportedEncodingException
*/
publicvoid parseRequest(HttpServletRequest request)
throws UnsupportedEncodingException {
DiskFileItemFactory factory =new DiskFileItemFactory();
factory.setSizeThreshold(sizeThreshold);
if (repository !=null)
factory.setRepository(repository);
ServletFileUpload upload =new ServletFileUpload(factory);
upload.setHeaderEncoding(encoding);
try{
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
String fieldName = item.getFieldName();
String value = item.getString(encoding);
parameters.put(fieldName, value);
}else{
if (!super.isValidFile(item)) {
continue;
}
if (fileItem ==null)
fileItem = item;
}
}
}catch (FileUploadException e) {
e.printStackTrace();
}
}
/** *//**
* 上傳文件, 調用該方法之前必須先調用 parseRequest(HttpServletRequest request)
* @param fileName 完整文件路徑
* @throws Exception
*/
publicvoid upload(String fileName) throws Exception {
File file =new File(fileName);
uploadFile(file);
}
/** *//**
* 上傳文件, 調用該方法之前必須先調用 parseRequest(HttpServletRequest request)
* @param parent 存儲的目錄
* @throws Exception
*/
publicvoid upload(File parent) throws Exception {
if (fileItem ==null)
return;
String name = fileItem.getName();
File file =new File(parent, name);
uploadFile(file);
}
privatevoid uploadFile(File file) throws Exception{
if (fileItem ==null)
return;
long fileSize = fileItem.getSize();
if (sizeMax >-1&& fileSize >super.sizeMax){
String message = String.format("the request was rejected because its size (%1$s) exceeds the configured maximum (%2$s)", fileSize, super.sizeMax);
thrownew org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException(message, fileSize, super.sizeMax);
}
String name = fileItem.getName();
fileItem.write(file);
}
/** *//**
* 獲取文件信息
* 必須先調用 parseRequest(HttpServletRequest request)
* @return
*/
public FileItem getFileItem() {
return fileItem;
}
}
支持多文件上傳的 MutiFileUpload 類:
MutiFileUpload.java
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
publicclass MutiFileUpload extends FileUploadBase {
private Map<String, FileItem> files;// 保存上傳的文件
privatelong filesSize =0; // 所有文件的總大小
publicvoid parseRequest(HttpServletRequest request)
throws UnsupportedEncodingException {
files =new HashMap<String, FileItem>();
// Create a factory for disk-based file items
DiskFileItemFactory factory =new DiskFileItemFactory();
factory.setSizeThreshold(sizeThreshold);
if (repository !=null)
factory.setRepository(repository);
ServletFileUpload upload =new ServletFileUpload(factory);
upload.setHeaderEncoding(encoding);
try{
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
String fieldName = item.getFieldName();
String value = item.getString(encoding);
parameters.put(fieldName, value);
}else{
if (super.isValidFile(item)) {
continue;
}
String fieldName = item.getFieldName();
files.put(fieldName, item);
filesSize += item.getSize();
}
}
}catch (FileUploadException e) {
e.printStackTrace();
}
}
/** *//**
* 上傳文件, 調用該方法之前必須先調用 parseRequest(HttpServletRequest request)
* @param parent 文件存儲的目錄
* @throws Exception
*/
publicvoid upload(File parent) throws Exception {
if (files.isEmpty())
return;
if (sizeMax >-1&& filesSize >super.sizeMax){
String message = String.format("the request was rejected because its size (%1$s) exceeds the configured maximum (%2$s)", filesSize, super.sizeMax);
thrownew SizeLimitExceededException(message, filesSize, super.sizeMax);
}
for (String key : files.keySet()) {
FileItem item = files.get(key);
String name = item.getName();
File file =new File(parent, name);
item.write(file);
}
}
public Map<String, FileItem> getFiles() {
return files;
}
}
當然還少不了過濾器 UploadFileFilter:
UploadFileFilter.java
publicinterface UploadFileFilter {
/** *//**
* 通過文件名后綴判斷文件是否被接受
* @param filename 文件名,不包括路徑
* @return
*/
publicboolean accept(String filename);
}
這樣在 Servlet 中我們就可以通過簡單的代碼實現文件的上傳了:
SingleFileUpload upload =new SingleFileUpload();
upload.parseRequest(request);
File parent =new File("C:\\upload\\");
try{
upload.upload(parent);
}
catch(org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException e){
// 文件大小超出最大值
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
相比 jspSmartUpload 我覺得 common-fileupload 有如下的優點:
1、開源;
2、Jakarta項目組的支持,開發十分活躍,而 jspSmartUpload 則已經停止開發了;
3、不需要寫入文件之前即可獲取到參數和文件信息,jspSmartUpload 則需要在獲取之前調用 upload 方法;
4、對中文支持友好。
轉自:http://www.cnblogs.com/yyw84/archive/2007/06/27/797652.html
轉載于:https://www.cnblogs.com/Ivan-j2ee/archive/2012/12/27/2836519.html
總結
以上是生活随笔為你收集整理的转 [JAVA] 使用 common-fileupload 实现文件上传的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ff15原画是谁画的呢?
- 下一篇: Cassandra 1.2 发布,NoS