一、文件上传的前提
a、提供form表单,method必须是post
b、form表单的enctype必须是multipart/form-data(默认是:application/x-www-form-urlencoded)
注:服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
c、提供input type="file"类的上传输入域
二、fileupload准备工作
a、fileupload的jar包:核心包(commons-fileupload.jar),依赖包(commons-io.jar)
b、fileupload组件使用步骤
1.创建工厂类DiskFileItemFactory对象:
DiskFileItemFactory factory = new DiskFileItemFactory()
2.使用工厂创建解析器对象:
ServletFileUpload fileUpload = new ServletFileUpload(factory)
3.使用解析器来解析request对象:
List<FileItem> list = fileUpload.parseRequest(request)
d、FileItem初步认识
1、对象对应一个表单项(表单字段)。可以是文件字段或普通字段
2、boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段
3、String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username
4、String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件
5、String getName():获取文件字段的文件名称(a.txt)
6、String getContentType():获取上传的文件的MIME类型,例如:text/plain
7、int getSize():获取上传文件的大小
8、InputStream getInputStream():获取上传文件对应的输入流
9、void write(File):把上传的文件保存到指定文件中
10、delete() 删除临时文件
a、安全(路径)问题:为保证服务器的安全,把保存上传文件的目录放在用户直接访问不到的地方,一般置于/WEB-INF/upload下
b、文件同名与文件夹中文件过多问题:
1、文件名前+UUID
2、创建子目录 按照日期进行打散存储目录,每天上传的文件的放在一个目录之下,适合文件不是特别多的情况
3、用文件名的hashCode计算打散的存储目录:二级目录,适合特别多的情况
c、限制文件的大小:web方式不适合上传大的文件
1、单个文件大小:ServletFileUpload.setFileSizeMax(1024*1024*5) //单个文件不超过5M.
2、多文件上传:ServletFileUpload.setSizeMax(字节)
d、处理中文乱码: 文件上传对象时 fileUpload.setHeaderEncoding("utf-8"); 获取字段内容 item.getString("utf-8");
e、设置临时文件的存放位置:factory.setRepository(new File("f:\\filestemp"));//创建工厂类对象时设置,地址要已存在。
临时文件的删除:item.delete();
f、写文件已经封装好代码:item.write,而且具有自动删除临时文件的功能
四、代码实现
a、我们先新建一个简单的jsp文件,例如:
<body>
<form enctype="multipart/form-data" action="${pageContext.request.contextPath }/servlet/UploadServlet" method="post">
<input type="text" name="info"></br>
<input type="file" name="files"></br>
<input type="file" name="photo"></br>
<input type="submit" value="提交">
</form>
</body>
uploadServlet实现:
package com.zgf.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import com.zgf.util.UUIDUtil;
public class UploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//先判断表单提交数据类型
boolean isMultipartForm = ServletFileUpload.isMultipartContent(request);//Content-Type multipart/form-data
if(!isMultipartForm)
throw new RuntimeException("Your form's Content-Type is not multipart/form-data.");
//创建工厂类对象
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File("f:\\filestemp"));//设置临时文件的存放位置
//创建文件上传对象
ServletFileUpload fileUpload = new ServletFileUpload(factory);
fileUpload.setHeaderEncoding("utf-8");//处理上传的中文乱码
try {
fileUpload.setFileSizeMax(1024*1024*3);//设置上传的文件的大小不能超过3M
fileUpload.setSizeMax(1024*1024*5);//控制上传的文件的总大小
//把表单提交过来的数据解析,把每个数据项封装成 FileItem对象----忘了,嘿嘿
List<FileItem> fileItems = fileUpload.parseRequest(request);
//获取每项数据
for(FileItem item:fileItems){
//判断是否是普通的数据项
if(item.isFormField()){
processFormField(item);
}else{
processFileUpload(item);
}
}
}catch(FileUploadBase.SizeLimitExceededException e){
System.out.println("上传的文件的总大小超过了5M");
}catch(FileUploadBase.FileSizeLimitExceededException e){
System.out.println("警告,文件不能超过3M");
}
catch (FileUploadException e) {
e.printStackTrace();
}
}
//处理上传文件的方法
private void processFileUpload(FileItem item) {
//在应用的目录下创建存储上传的文件的目录
//把目录创建在WEB-INF下是为了安全
String storeDirectory = this.getServletContext().getRealPath("/WEB-INF/upload");
File realDirectory = new File(storeDirectory);
if(!realDirectory.exists())
realDirectory.mkdirs();
try {
//读取文件的读取流
InputStream in = item.getInputStream();
//得到上传文件名
String fileName = item.getName();//ie浏览器 F:\pic\deng2.jpg 火狐 deng2.jpg
//截取文件名
//fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
fileName = FilenameUtils.getName(fileName);//使用工具类处理文件名
//处理文件名同名的问题
fileName = UUIDUtil.getUUID()+"_"+fileName;
//处理把文件放在不同的文件夹下
String childDirectory = getChildDirectory2(realDirectory,fileName);//"2016-09-30"
File fileDir = new File(realDirectory,childDirectory+File.separator+fileName);
FileOutputStream fos = new FileOutputStream(fileDir);
byte[] arr = new byte[1024];
int len = 0;
while((len=in.read(arr))!=-1)
{
fos.write(arr,0,len);
}
//删除临时文件
item.delete();
in.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//创建子目录:用哈希值
private String getChildDirectory2(File realDirectory, String fileName) {
int hashCode = fileName.hashCode();
String code = Integer.toHexString(hashCode);//把哈希值转成16进制
String childDirectory = code.charAt(0)+File.separator+code.charAt(1);// a/b a/a a/c a/d b/a b/b b/c
File dir = new File(realDirectory,childDirectory);
if(!dir.exists())
dir.mkdirs();
return childDirectory;
}
//创建子目录:用时间
private String getChildDirectory(File realDirectory) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String time = sdf.format(date);// "2016-10-05"
File dir = new File(realDirectory,time);
if(!dir.exists())
dir.mkdirs();
return time;
}
//处理普通表单项的方法
private void processFormField(FileItem item) {
//得到名字--jsp中文本框的名字
String name = item.getFieldName();
//得到值
String value ="";
try {
value = item.getString("utf-8");//处理中文乱码
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(name+"="+value);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
代码优化:
uploadServlet实现:
package com.zgf.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import com.zgf.util.UUIDUtil;
public class UploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//判断表单提交数据类型
boolean isMultipartForm = ServletFileUpload.isMultipartContent(request);//Content-Type multipart/form-data
if(!isMultipartForm)
throw new RuntimeException("Your form's Contet-Type is not multipart/form-data.");
//创建工厂类对象
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File("f:\\filestemp"));//设置临时文件的存放位置--事先存在
//创建文件上传对象
ServletFileUpload fileUpload = new ServletFileUpload(factory);
fileUpload.setHeaderEncoding("utf-8");//处理上传的中文乱码
try {
fileUpload.setFileSizeMax(1024*1024*3);//设置上传的单个文件的大小不能超过3M
fileUpload.setSizeMax(1024*1024*5);//控制上传的文件的总大小
//把表单提交过来的数据解析,把每个数据项封装成 FileItem对象
List<FileItem> fileItems = fileUpload.parseRequest(request);
//获取每项数据
for(FileItem item:fileItems){
//判断是否是普通的数据项
if(item.isFormField()){
processFormField(item);
}else{
processFileUpload(item);
}
}
}catch(FileUploadBase.SizeLimitExceededException e){
System.out.println("上传的文件的总大小超过了5M");
}catch(FileUploadBase.FileSizeLimitExceededException e){
System.out.println("警告,文件不能超过3M");
}
catch (FileUploadException e) {
e.printStackTrace();
}
}
//处理上传文件的方法
private void processFileUpload(FileItem item) {
//在应用的目录下创建存储上传的文件的目录
//把目录创建在WEB-INF下是为了安全
String storeDirectory = this.getServletContext().getRealPath("/WEB-INF/upload");
File realDirectory = new File(storeDirectory);
if(!realDirectory.exists())
realDirectory.mkdirs();
try {
//读取文件的读取流
//InputStream in = item.getInputStream();
//得到上传文件名
String fileName = item.getName();//ie浏览器 F:\pic\deng2.jpg 火狐 deng2.jpg
//截取文件名
//fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
fileName = FilenameUtils.getName(fileName);//使用工具类处理文件名
//处理文件名同名的问题
fileName = UUIDUtil.getUUID()+"_"+fileName;
//处理把文件放在不同的文件夹下-- getChildDirectory
//String childDirectory = getChildDirectory2(realDirectory,fileName);//"2016-10-05"
String childDirectory = getChildDirectory(realDirectory);
//自动删除临时文件的功能--路径:WEB-INF/upload 8/3 / UUID_哈哈.txt
item.write(new File(realDirectory,childDirectory+File.separator+fileName));
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//创建子目录:用哈希值
private String getChildDirectory2(File realDirectory, String fileName) {
int hashCode = fileName.hashCode();
String code = Integer.toHexString(hashCode);//把哈希值转成16进制
String childDirectory = code.charAt(0)+File.separator+code.charAt(1);// a/b a/a a/c a/d b/a b/b b/c
File dir = new File(realDirectory,childDirectory);
if(!dir.exists())
dir.mkdirs();
return childDirectory;
}
//创建子目录:用时间
private String getChildDirectory(File realDirectory) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String time = sdf.format(date);// "2016-09-30"
File dir = new File(realDirectory,time);
if(!dir.exists())
dir.mkdirs();
return time;
}
//处理普通表单项的方法
private void processFormField(FileItem item) {
//得到名字
String name = item.getFieldName();
//得到值
String value ="";
try {
value = item.getString("utf-8");//处理中文乱码
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(name+"="+value);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}