使用 common-fileupload 实现文件上传

本文介绍了一个文件上传组件Commons FileUpload的使用方法,包括单文件和多文件上传的封装类及过滤器,解决了中文参数支持问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 就在前段时间,还在苦于找到不到合适的上传组件,虽然很早就知道了 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;

public   abstract   class  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.
     
*/

    
protected int 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.
     * 
     
*/

    
protected long 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;
    }


    
public void setEncoding(String encoding) {
        
this.encoding = encoding;
    }


    
/** *//**
     * 获取上传文件最大的大小,单位为Byte(字节),为-1时表示无限制
     * 
@return
     
*/

    
public long getSizeMax() {
        
return sizeMax;
    }


    
/** *//**
     * 设置上传文件最大的大小,单位为Byte(字节),为-1时表示无限制
     * 
@param sizeMax
     
*/

    
public void setSizeMax(long sizeMax) {
        
this.sizeMax = sizeMax;
    }


    
public int getSizeThreshold() {
        
return sizeThreshold;
    }


    
public void 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()
     * 
     
*/

    
public void setRepository(File repository) {
        
this.repository = repository;
    }

    
    
/** *//**
     * 获取参数列表
     * 
@return
     
*/

    
public Map<String, String> getParameters() {
        
return parameters;
    }


    
/** *//**
     * 获取过滤器
     * 
@return
     
*/

    
public UploadFileFilter getFilter() {
        
return filter;
    }


    
/** *//**
     * 设置文件过滤器,不符合过滤器规则的将不被上传
     * 
@param filter
     
*/

    
public void setFilter(UploadFileFilter filter) {
        
this.filter = filter;
    }

    
    
/** *//**
     * 验证文件是否有效
     * 
@param item
     * 
@return
     
*/

    
protected boolean 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;

public   class  SingleFileUpload  extends  FileUploadBase  {
    
private FileItem fileItem;

    
/** *//**
     * 
     * 
@param request
     * 
@throws UnsupportedEncodingException
     
*/

    
public void 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
     
*/

    
public void upload(String fileName) throws Exception {
        File file 
= new File(fileName);
        uploadFile(file);
    }


    
/** *//**
     * 上传文件, 调用该方法之前必须先调用 parseRequest(HttpServletRequest request)
     * 
@param parent 存储的目录
     * 
@throws Exception
     
*/

    
public void upload(File parent) throws Exception {
        
if (fileItem == null)
            
return;

        String name 
= fileItem.getName();
        File file 
= new File(parent, name);
        uploadFile(file);
    }

    
    
private void 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);
                    
            
throw new 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;

public   class  MutiFileUpload  extends  FileUploadBase  {

    
private Map<String, FileItem> files;// 保存上传的文件
    private long filesSize = 0// 所有文件的总大小


    
public void 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
     
*/

    
public void 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);
                    
            
throw new 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
public   interface  UploadFileFilter  {
    
/** *//**
     * 通过文件名后缀判断文件是否被接受
     * 
@param filename 文件名,不包括路径
     * 
@return
     
*/

    
public boolean 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、对中文支持友好。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值