当前位置: 首页 > 编程日记 > 正文

转 [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

相关文章:

Cachegrind--缓存命中检查工具及其可视化

Cachegrind–缓存命中检查工具及其可视化 和 Callgrind–函数调用分析工具以及可视化方法 一模一样 命令改为: valgrind --toolcachegrind ./palmGateMachine 生成的文件名: cachegrind.out.8025 用kcachegrind 打开 参考我的另一篇文章&#xff1a; https://editor.csdn.…

java 快排_八大排序-快速排序(搞定面试之手写快排)

概要快速排序由C. A. R. Hoare在1960年提出&#xff0c;是八大排序算法中最常用的经典排序算法之一。其广泛应用的主要原因是高效&#xff0c;核心算法思想是分而治之。快速排序经常会被作为面试题进行考察&#xff0c;通常的考察思路是快排思想、编码实践之手写快排以及进一步…

maven命令简介

为什么80%的码农都做不了架构师&#xff1f;>>> 创建普通应用项目&#xff1a; mvn archetype:create -DgroupIdcom.byread -DartifactIdblog 创建WEB项目&#xff1a; mvn archetype:create -DgroupIdcom.byread -DartifactIdblogweb -DarchetypeArtifactIdmav…

分治策略解决幂乘问题

float fast_pow ( float x, float y ) {if ( y 1 )return x;else if ( (int)y % 2 0 )return fast_pow(x,y/2)*fast_pow(x,y/2);elsereturn fast_pow(x,(y-1)/2)*fast_pow(x,(y-1)/2)*x; } 转载于:https://www.cnblogs.com/Nicholastwo/p/9368076.html

用java实现一个计算器程序_1.2第一个java程序——hello world

第一个java程序——hello world实现一个java程序&#xff0c;主要有三个步骤&#xff1a;1、编写源代码&#xff0c;2、编译源代码&#xff0c;3、运行。java的源代码必须先编译&#xff0c;然后才能由JVM解析执行。所以我们程序员第一步的工作就是要编写java的源代码文件&…

linux valgrind Memcheck--内存检查工具

linux valgrind Memcheck–内存检查工具 使用方法: 注意&#xff0c;这里要用debug版本&#xff0c;如果是release的运行文件&#xff0c;则用debug编译出来的可执行文件替换 输出到终端: valgrind --toolmemcheck --leak-checkfull ./test.out输出到文件: valgrind --toolm…

Cassandra 1.2 发布,NoSQL 数据库

NoSQL 数据库 Cassandra 发布 1.2 正式版&#xff0c;该版本包含 CQL3&#xff0c;这是在 2012年4月发布的 1.1 版本中引入的。CQL 是一个 Cassandra 的建模和查询语言&#xff0c;类似关系数据库中的 SQL。CQL3 支持多列主键和很多其他的改进。 Another Cassandra 1.2 主要的增…

CQRS实践(3): Command执行结果的返回

上篇随笔讨论了CQRS中Command的一种基本实现。 面对UI中的各种命令&#xff0c;Controller会创建相应的Command对象&#xff0c;然后将其交给CommandBus&#xff0c;由CommandBus统一派发到相应的CommandExecutor中去执行&#xff0c;我们的ICommandBus的接口声明如下: public …

iOS学习——核心动画之Layer基础

iOS学习——核心动画之Layer基础 1、CALayer是什么&#xff1f; CALayer我们又称它叫做层。在每个UIView内部都有一个layer这样一个属性&#xff0c;UIView之所以能够显示&#xff0c;就是因为它里面有这个layer才具有显示的功能。我们可以通过操作CALayer对象&#xff0c;可以…

linux valgrind memCheck ---内存检查工具的可视化方法valkyrie

linux valgrind memCheck —内存检查工具的可视化方法valkyrie linux valgrind Memcheck–内存检查工具 1、安装valgrind valgrind 安装 安装过程没这么复杂。 直接命令行: sudo apt-get install valgrind2、安装valkyrie valkyrie下载连接: https://launchpad.net/ubuntu/…

屏幕为什么要正负压供电_负压变换器的设计

目前在工业、汽车电子系统中有诸如温度、压力、位置、重量和流量等物理参数的精确测量&#xff0c;这些信号中的一些传感器和前置放大器需要正负电压源驱动或供电&#xff0c;以提供足够宽的动态范围和抗干扰性。这些电子系统通常使用3.3V、5V、12V或24V中的某一电压的直流电源…

DataCleaner 3.1.1 发布,数据质量分析管理

DataCleaner 3.1.1 扩展了日期和时间相关的分析&#xff1b;增加周、月、年的分布分析&#xff1b;数值分析和日期时间分析增加了描述统计的选项&#xff1b;新增用于生成 UUID 和时间戳的转换器等等。 DataCleaner 是一个数据质量分析&#xff0c;比较&#xff0c;验证和监督的…

IIS负载均衡-Application Request Route详解第三篇:使用ARR进行Http请求的负载均衡(上)...

IIS负载均衡-Application Request Route详解第三篇&#xff1a;使用ARR进行Http请求的负载均衡&#xff08;上&#xff09; 在前两篇文章中&#xff0c;我们已经讲述如何配置与安装ARR&#xff0c;从本篇文章开始&#xff0c;我们将重点的来讲述如何在使用ARR进行负载均衡。 本…

云主机启动提示Booting from Hard Disk GRUB

版本&#xff1a;Openstack ocata 系统&#xff1a;centos7.3 环境&#xff1a;VMware workstation12 解决方法&#xff1a; 或者 转载于:https://www.cnblogs.com/fcing/p/9374855.html

函数 tostring_Kotlin实战之Fuel的高阶函数

Fuel 是一个用 Kotlin 写的网络库&#xff0c;与 OkHttp 相比较&#xff0c;它的代码结构比较简单&#xff0c;但是它的巧妙之处在于充分利用了 Kotlin 的语言特性&#xff0c;所以代码看上去干净利落。OkHttp 使用了一个 interceptor chain 来实现拦截器的串联调用&#xff0c…

linux valgrind 安装和使用

linux valgrind 安装和使用 安装过程没这么复杂。 直接命令行: sudo apt-get install valgrind Valgrind 是个开源的工具&#xff0c;功能很多。例如检查内存泄漏工具—memcheck。 Valgrind 安装&#xff1a; sudo apt-get install valgrind Valgrind 命令介绍&#xff…

UIPopoverController在ARC环境下用法注意

在ARC环境下如果便用以下代码&#xff1a; [cpp] view plaincopyprint?UIViewController *viewTwo; viewTwo [[ViewTwo alloc] initWithNibName:"ViewTwo" bundle:nil]; UIPopoverController *popover; popover [[UIPopoverController alloc] initWithConten…

CPLD的分频语言

分频器在FPGA/CPLD设计中是不可缺少的一部分&#xff0c;这就包括分频系数是奇数和偶数的&#xff08;我们称为奇分频和偶分频&#xff09;&#xff0c;而对于偶分频来说还有不同的分频方法&#xff0c;下面将给出具体的方法&#xff1a; 1、占空比不为50%的偶分频 占空比&…

彻底解决web开发中遇到的路径问题(上)

注&#xff1a;本文部分引用了网络上的文章&#xff0c;以及动力节点老师的讲解内容&#xff0c;感谢老师&#xff0c;嘻嘻。 为了举例方便&#xff0c;我新建了pathTest项目&#xff1a; 关于tomcat的配置&#xff0c;eclipse访问项目的路径一般是localhost:8080/projectName,…

关于Page翻页效果--Page View Controller

Page View Controllers你使用一个page view controller用page by page的方式来展示内容。一个page view controller管理一个self-contained视图架构。这个架构的父视图由page View controller管理&#xff0c;并且子视图由你提供的view Controllers管理。一&#xff0c;解析Pag…

linux平台下QtCreator中集成Valgrind系列工具

linux平台下QtCreator中集成Valgrind系列工具 ###1、valgrind 安装 valgrind 安装 2、打开QtCreator >> Analyze 你就会发现 这里已经有valgrind的相关选项了 如果没有的话&#xff0c; 在help >> about plugin >> C 中勾选 如图: 点击则可以直接运行…

python输入参数改变图形_Python基于Tensor FLow的图像处理操作详解

本文实例讲述了Python基于Tensor FLow的图像处理操作。分享给大家供大家参考&#xff0c;具体如下&#xff1a;在对图像进行深度学习时&#xff0c;有时可能图片的数量不足&#xff0c;或者希望网络进行更多的学习&#xff0c;这时可以对现有的图片数据进行处理使其变成一张新的…

CSS层叠样式

为了让网页元素的样式更加丰富&#xff0c;也为了让网页的内容和样式能拆分开&#xff0c;CSS由此思想而诞生&#xff0c;CSS是 Cascading Style Sheets 的首字母缩写&#xff0c;意思是层叠样式表。有了CSS&#xff0c;html中大部分表现样式的标签就废弃不用了&#xff0c;htm…

windows下 Source Monitor代码度量工具的使用

windows下 Source Monitor代码度量工具的使用 引用链接: https://www.cnblogs.com/xuehanyu/p/4520965.html 1.总体介绍 SourceMonitor是一款免费的软件&#xff0c;运行在Windows平台下。它可对多种语言写就的代码进行度量&#xff0c;包括C、C、C#、Java、VB、Delphi和HT…

MVVM 数据绑定

一、在 XAML 中创建绑定 定义源对象。 C# public class Dog {public string DogName { get; set; } }在 XAML 中创建对源对象的命名空间的引用。 XAML <UserControl x:Class"BindingXAML.Page" xmlns"http://schemas.microsoft.com/winfx/2006/xaml/pres…

linux配置文件怎么把某行后几个字符替换_vim(Linux运维)

一、vim使用介绍 介绍在linux系统中&#xff0c;大部分配置文件都是ASCII的纯文本形式存放的&#xff0c;所以我们在修改系统设置的时候使用简单的文本编辑软件就可以实现了&#xff0c;如果你使用过windows当中的word的话&#xff0c;那么你可能会感觉linux字符界面的文本编辑…

Debian 6.0 安装过程 及中文乱码

2019独角兽企业重金招聘Python工程师标准>>> Debian 6.0 安装过程 Debian 6.0 安装过程 转(一个别人自录的安装过程录相) http://v.youku.com/v_show/id_XMjUyMzY1OTIw.html 转(别人写的一个过程) http://hi.baidu.com/ljx_freebsd/blog/item/88d60c09da379da22edd…

git 提交丢失Warning, you are leaving 2 commits behind,

早上在自己的一个版本代码上编辑&#xff0c;提交commint&#xff0c;但是checkout到其他分支再checkout回来发现该的东西不见了&#xff0c; 幸好terminal还没有关掉&#xff0c;回看日志&#xff1a; Warning: you are leaving 2 commits behind, not connected toany of you…

一台支持vlan管理的交换机_关于交换机的VLAN技术你了解多少?

VLAN&#xff08;虚拟局域网&#xff09;是对连接到的第二层交换机端口的网络用户的逻辑分段&#xff0c;不受网络用户的物理位置限制而根据用户需求进行网络分段。一个VLAN可以在一个交换机或者跨交换机实现。VLAN可以根据网络用户的位置、作用、部门或者根据网络用户所使用的…

需要反射时使用dynamic

//使用dynamic的写法 dynamic fileExplorerData _currentFolder.FileExplorerData; var data fileExplorerData.InsertFromPath(newPath);//使用反射的写法 MethodInfo InsertMethod _currentFolder.FileExplorerData.GetType().GetMethod("InsertFromPath"); var…