Java 文件上传处理库,Fastupload 0.5.3 发布
相对于以往的版本,fastupload 0.5.3做出了明显的增强和修改。此版本中,“融合“了磁盘解析方式和内存解析方式,磁盘解析方式也支持非文件类型输入的解析,减少了磁盘解析模式中 UploadChunk对象的创建,提升了解析性能,改进了字符编码转换,API更加简明。
基本API使用
默认情况下,fastupload建议使用内存解析模式,因为这种模式下解析的性能是最好的,而且,解析出的数据是在内存中,很容易处理。其API使用如下,
FastUploadParser fastUploadParser = new FastUploadParser(request); List<MultiPart> list = fastUploadParser.parseList(); for (MultiPart e: list){ if (e.isFile()){ System.out.format("input field name: %s, file name:%s%n", e.getFieldName(), e.getFileName()); e.toFile( /file/ ) ; //write data to a file where you want to place } else { System.out.format("input field name: %s, value:%s%n", e.getFieldName(), e.getString()); } }
但是在某些特定的情况下,比如对内存的使用限制要求强烈的场合,或者上传的文件非常大,可以使用磁盘解析模式,这种模式下,API的使用与内存模式基本相同,只不过需要创建FileFactory对象,并把这个对象作为FastUploadParser构造函数的第二个参数。
FileFactory fileFactory = FileFactory.getInstance(); fileFactory.setRepository(System.getProperty("user.home")+"/fastupload"); FastUploadParser fastUploadParser = new FastUploadParser(request, fileFactory); List<MultiPart> list = fastUploadParser.parseList(); for (MultiPart e: list){ if (e.isFile()){ System.out.format("input field name: %s, file name:%s%n", e.getFieldName(), e.getFileName()); e.toFile( /target/ ) ; //move temporary file to where you want to place } else { System.out.format("input field name: %s, value:%s%n", e.getFieldName(), e.getString()); } }
在这种模式下,当从multipart/form-data输入流中发现有上传的文件时,会在FileFactory指定的目录内创建一个临时文件,每次写入不超过8k的数据,此文件的数据分析完后,关闭文件。因此,要使用e.toFile(...) 函数把这个临时文件移至你所想要的地方,对于非文件类型的输入,e.getString()输出其内容。
高级特性
有时候,需要限制客户端上传的文件,不同于其他的文件解析组建,Fastupload采用预先特性匹配机制,在解析过程中,一旦发现头信息与设定的模式不匹配时,会自动跳过此部分。API使用如下
FileFactory fileFactory = FileFactory.getInstance(); fileFactory.setAllowedTypes("image/jpeg"); fileFactory.setAllowedExtensions(".jpg, .png");
当然,文件大小的限制,也是必须要支持的,下面的第一行代码是设定每个文件不超过200000字节,第二行代码是设定multipart输入流的总大小不超过2000000字节,注意,这里的总数是包含一些HTML的代码在内的
fileFactory.setThreshold(200000); fileFactory.setMaxContentLength(2000000);
如果想知道解析的进度,可以创建一个ProgressListener对象
ProgressListener listener = new ProgressListener(fastUploadParser); listener.progress();
字符编码
java语言本身是支持unicode的,并且,在各种unicode之间进行转换是很容易的,但是比较杯具的是,在Servlet规范中,没有规定检测传输的数据所采用的编码方法,在服端编程时,没有调用ServletRequest.setCharsetEncoding(...) 函数时,ServletRequest.getCharsetEncoding(...) 函数永远返回null,在程序里,很难知道客户端发送过来的数据流是采用以什么字符集进行编码的。不仅如此,即使知道了数据流编码所采用的字符集,可能和运行着的Servlet容器所使用的字符集不一样,可能和操作系统所使用的字符集也不一样,因此对数据流进行适当的字符集转换,并按照Servlet容器所使用的字符保存到文件系统,对于防范由字符编码引起的问题。
在unicode环境中,首先要告诉ServletRequest,客户端发送数据时编码所采用的字符集,給FileFactory设置目标字符集,如果不想显式初始化带有编码的FileFactory对象,可以在启动JVM时加上 -Dfile.encoding="UTF-8"参数,FileFactory会取这个默认的字符集。
request.setCharsetEncoding(“gbk"); FileFactory fileFactory = FileFactory.getInstance("utf-8"); // ... 以下省略解析代码
对于磁盘解析方式,正确的设定了ServletRequest编码字符集和目标字符集后,文本文件可以进行正确的转码。有一点需要注意的是,即使是文本文件,浏览器按照二进制流的形式把其内容“灌入”到HTTP流中,当对其文件名却按照浏览器当前的字符集进行编码,假如文本文件保存的时候,编码是 gbk,用浏览器上传文件时选用了utf8,这样,fastupload就不能正确的进行转码工作。因此在磁盘解析模式下,有必要让浏览器采用和操作系统同样的编码。
而对于内存解析方式,API使用者代码可以直接访问到二进制的流,可以随心所欲的进行编码转换工作。
1, MultiPart part ...; 2, part.getString(); 3, part.getString("gbk");
这个代码片段中,第二行是对解析到的流按照系统默认的字符集转换成String,第三行是按照指定的字符集对字节流进行编码,转换成String。
@仪山湖
项目地址:https://sourceforge.net/projects/fastupload/
项目wiki: https://sourceforge.net/p/fastupload/wiki/Fastupload%20Home/