? 如果在表单中使用表单元素<input type=“file” />,浏览器在解析表单时,会自动生成一个输入框和一个按钮,输入框可供用户填写本地文件的文件名和路径名,按钮可以让浏览器打开一个文件选择框供用户选择文件:
Enctype 属性
在 Commons-fileupload 组件中,主要用到以下三个接口和类:
ServletFileUpload 负责处理上传的文件数据,并将每部分的数据封装成一到 FileItem 对象中。
DiskFileItemFactory 是创建 FileItem 对象的工厂,在这个工厂类中可以配置内存缓冲区大小和存放临时文件的目录。
ServletFileUpload 在接收上传文件数据时,会将内容保存到内存缓存区中,如果文件内容超过了 DiskFileItemFactory 指定的缓冲区的大小,那么文件将被保存到磁盘上,存储为 DiskFileItemFactory 指定目录中的临时文件。等文件数据都接收完毕后,ServletUpload 在从文件中将数据写入到上传文件目录下的文件中。
DiskFileItemFactory 是创建FileItem 对象的工厂,这个工厂类常用方法:
ServletFileUpload 负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem 对象中。常用方法有:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录。
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024 * 500);
File tempDirectory = new File("d:\\tempDirectory");
factory.setRepository(tempDirectory);
//2、使用DiskFileItemFactory 对象创建ServletFileUpload对象,并设置上传文件的大小限制。
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(1024 * 1024 * 5);
try {
//3、调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。
List<FileItem> items = upload.parseRequest(req);
//4、对list进行迭代,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件:
for (FileItem item : items) {
//4.1、 为普通表单字段,则调用getFieldName、getString方法得到字段名和字段值。
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
System.out.println(name + ": " + value);
}
//4.2、为上传文件,则调用getInputStream方法得到数据输入流,从而读取上传数据。
else {
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
long sizeInBytes = item.getSize();
System.out.println(fieldName);
System.out.println(fileName);
System.out.println(contentType);
System.out.println(sizeInBytes);
InputStream in = item.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
File file = new File("d://files");
if (!file.exists()){
file.mkdir();
}
fileName = "d:\\files\\" + fileName;
System.out.println(fileName);
OutputStream out = new FileOutputStream(fileName);
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
in.close();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
byte[] b = new byte[1024];
int len = 0;
while((len=is.read(b))> 0){
out.write(b, 0, len);
}
is.close();
步骤:
至此实际上文件下载的主要功能都已经完成。但是还有一个问题我们这里没有体现出来,因为目前我们的文件名使用的是纯英文的,没有乱码问题。这里如果我们要使用中文文件名的话,毫无疑问会出现乱码问题。
解决此问题的方法很简单,在获取文件名之后为文件名进行编码:
fileName = java.net.URLEncoder.encode(filename,"utf-8");
或者先用GBK解码,再使用iso8859-1编码
fileName = new String(name.getBytes("gbk"),"iso8859-1");
但是注意这里火狐浏览器比较特殊,因为他默认是以BASE64解码的,所以这块如果需要考虑火狐的问题的话还需要特殊处理一下。
先要获取客户端信息(通过获取请求头中的User-Agent信息)
//获取客户端信息
String ua = request.getHeader("User-Agent")
然后判断浏览器版本,做不同的处理(通过判断头信息中是否包含Firefox字符串来判断浏览器版本)
//判断客户端是否为火狐
if(ua.contains("Firefox")){
//若为火狐使用BASE64编码
filename = "=?utf-8?B?"+new BASE64Encoder()
.encode(filename.getBytes("utf-8"))+"?=";
}else{
//否则使用UTF-8
filename = URLEncoder.encode(filename,"utf-8");