文件上传页面条件:
1. 必须提交表单,而且这个表单必须使用post提交方式提交。
2. 表单里面必须有一个<input type="file"/>,,使用file组件来上传文件
3. 表单的enctype必须设置为multipart/form-data内容
<form action="${pageContext.request.contextPath }/UploadDemo1" method="post" enctype="multipart/form-data">
请选择上传的文件1:<input type="file" name="attachment1"/>
请选择上传的文件2:<input type="file" name="attachment2"/>
<input type="submit" value="上传"/>
</form>
使用fileupload组件进行处理上传文件:
- 导入jar包
commons-fileupload-1.2.2.jar 核心包
commons-io-2.1.jar 辅助包
- 核心的API
DiskFileItemFactory类: 用于设置上传文件的缓存大小和缓存目录。
ServletFileUpluad类: 用于解析上传的所有文件
List<FileItem>: parserRequest(HttpSevletRequest request): 解析上传的文件
FileItem对象: 代表一个上传的文件
文件名称
大小
类型
内容
单文件上传
upload.jsp
<form action="${pageContext.request.contextPath }/UploadDemo1" method="post" enctype="multipart/form-data">
请选择上传的文件1:<input type="file" name="attachment1"/><br/>
<input type="submit" value="上传"/>
</form>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//1)创建DiskFileItemFactory对象,用于设置缓存大小,和缓存目录
/**
* 参数一: 缓存大小。如果文件大小<缓存大小,那么该文件直接传到服务器,不通过缓存。否则,就先把文件存储到缓存目录,然后再从缓存目录转移到指定保存目录中。
* 参数二: 缓存目录。 提供给缓存文件存储的地址
*/
DiskFileItemFactory factory = new DiskFileItemFactory(); //10k(默认也是10k)
//2)使用ServletFileUpload解析文件
ServletFileUpload upload = new ServletFileUpload(factory);
/**
* 注意:通过设置文件头编码格式来解决文件名称中文乱码问题
*/
upload.setHeaderEncoding("utf-8");
//3)解析文件
List<FileItem> list = upload.parseRequest(request);//该方法会自动读取请求的实体内容中所有上传文件的信息
//4)读取上传文件的信息
if(list!=null){
//取出第一个文件
FileItem item = list.get(0);
//文件信息
String name = item.getName();
//表单对应字段名
String fieldName = item.getFieldName();
//大小
long size = item.getSize();
//类型
String contentType = item.getContentType();
//文件内容
InputStream in = item.getInputStream();
//使用IO流工具,写出到服务器的硬盘上去
FileUtils.copyInputStreamToFile(in, new File("d:/files/"+name));//目录不存在会自动创建
//注意:文件上传成功处理完之后,应该把临时文件删除
item.delete();
System.out.println("文件名:"+name);
System.out.println("文件大小:"+size);
System.out.println("文件类型:"+contentType);
System.out.println("表单字段名:"+fieldName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
多文件上传
upload.jsp
<form action="${pageContext.request.contextPath }/UploadDemo2" method="post" enctype="multipart/form-data">
请选择上传的文件1:<input type="file" name="attachment1"/><br/>
请选择上传的文件2:<input type="file" name="attachment2"/><br/>
<input type="submit" value="上传"/>
</form>
success.jsp
<h3>文件上传成功! </h3>
<table border="1" width="500px">
<tr>
<th>编号</th>
<th>文件名</th>
<th>大小</th>
<th>类型</th>
<th>上传时间</th>
</tr>
<c:forEach items="${fileList}" var="bean" varStatus="varSta">
<tr>
<td>${varSta.count }</td>
<td>${bean.name }</td>
<td>${bean.size }</td>
<td>${bean.type }</td>
<td>${bean.addTime }</td>
</tr>
</c:forEach>
</table>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
DiskFileItemFactory factory = new DiskFileItemFactory(10*1024,new File("d:/temp"));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");
//解析
List<FileItem> list = upload.parseRequest(request);
List<FileBean> fileList = new ArrayList<FileBean>();
//处理文件
for (FileItem item : list) {
String name = item.getName();
long size = item.getSize(); //b
String contentType = item.getContentType();
//封装文件信息
FileBean bean = new FileBean();
/**
* e.g. 1024b=1KB 1024*1024b=1MB
*/
String sizeStr = "";
if(size>=1024 && size<1024*1024){
sizeStr = (size/1024.0)+"KB";
}else if(size>1024*1024 && size<=1024*1024*1024){
sizeStr = (size/(1024*1024.0))+"MB";
}else if(size >= 1024*1024*1024){
sizeStr = (size/(1024*1024.0*1024))+"GB";
}else{
sizeStr = size+"B";
}
bean.setName(name);
bean.setSize(sizeStr);
bean.setAddTime(sdf.format(new Date()));
bean.setType(contentType);
fileList.add(bean);
//把文件保存到硬盘
FileUtils.copyInputStreamToFile(item.getInputStream(), new File("d:/files/"+name));
//删除临时文件
item.delete();
}
request.setAttribute("fileList", fileList);
//跳转到成功页面,显示成功的所有文件列表
request.getRequestDispatcher("/success.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
文件上传注意事项
- 文件重名
- 文件大小限制
- 文件类型限制
- 获取其他field字段内容
<body>
<font color="red">${msg }</font>
<form action="${pageContext.request.contextPath }/UploadDemo3" method="post" enctype="multipart/form-data">
请选择上传的文件1:<input type="file" name="attachment1" />描述1: <input type="text" name="info1"/><br/>
请选择上传的文件2:<input type="file" name="attachment1" />描述2: <input type="text" name="info2"/><br/>
<!--
请选择上传的文件3:<input type="file" name="attachment1" /><br/>
请选择上传的文件4:<input type="file" name="attachment1" /><br/>
请选择上传的文件5:<input type="file" name="attachment1" /><br/>
-->
<input type="submit" value="上传"/>
</form>
</body>
public class UploadDemo3 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
DiskFileItemFactory factory = new DiskFileItemFactory(10*1024, new File("d:/temp"));
ServletFileUpload upload = new ServletFileUpload(factory);
/**
* 注意: 注册一个文件上传的监听器
*/
//upload.setProgressListener(new MyProgressListener());
upload.setHeaderEncoding("utf-8");
/**
* 注意: 设置限制文件上传的大小
*/
upload.setFileSizeMax(100*1024);//单个文件大小
upload.setSizeMax(300*1024);//总文件大小
List<FileItem> list = upload.parseRequest(request);
/**
* 尝试获取上传表单的输入域的数据
* 注意:
* 1)因为表单已经是multipart/form-data类型,text组件数据格式已经发送改变,类似file组件的格式。
* 2)text组件已经被fileUpload组件同样封装到FileItem对象中。
*
*/
/* String info1 = request.getParameter("info1");
System.out.println("info1"+info1);*/
if(list!=null){
for(FileItem item: list){
if(item.isFormField()){
//除file组件外的其他表单组件(text/password/select/hidden。。。。。)
//取出text组件内容
/**
* getFieldName()获取表单组件的name属性值
*/
if(item.getFieldName().equals("info1")){
String info1 = item.getString("utf-8");
System.out.println("info1="+info1);
}
if(item.getFieldName().equals("info2")){
String info2 = item.getString("utf-8");
System.out.println("info2="+info2);
}
}else{
//file组件
/**
* 注意:限制文件的类型。 文件的mime-type: image/*
* 需求: 只能上传图片.
*/
//得到文件的类型
// String contentType = item.getContentType();
// if(!contentType.contains("image/")){
// //非法的文件类型
// throw new FileTypeErrorException("文件类型错误,请换一张!!");
// }
/**
* 注意: 使用UUID算法生成唯一的文件名,避免因为文件名相同覆盖原有的文件
*/
String uuid = UUID.randomUUID().toString();
String fileName = item.getName();
//后缀名
String prefixName = fileName.substring(fileName.lastIndexOf("."));
//新文件名
String newFileName = uuid+prefixName;
//新的目录结构
String baseDir = "d:/files/";
String subDir = makeDirectory(newFileName);//使用算法生成的子目录结构
String finalDir = baseDir + subDir;
//生成目录结构
File file = new File(finalDir);
if(!file.exists()){
//构建目录结构
file.mkdirs();
}
//保存
FileUtils.copyInputStreamToFile(item.getInputStream(), new File(finalDir+newFileName));
//删除临时文件
item.delete();
}
}
}
}
// catch(FileTypeErrorException e){ //先捕获业务异常进行处理
// request.setAttribute("msg", e.getMessage());
// request.getRequestDispatcher("/upload.jsp").forward(request, response);
// }
catch(FileSizeLimitExceededException e){
request.setAttribute("msg", "单个文件超过设定大小:100KB");
request.getRequestDispatcher("/upload.jsp").forward(request, response);
} catch(SizeLimitExceededException e){ //捕获超过总文件大小的异常
request.setAttribute("msg", "超过总文件大小:300KB");
request.getRequestDispatcher("/upload.jsp").forward(request, response);
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 返回新的目录结构: e.g 11(第一级目录)/2(第二级目录)
*/
private String makeDirectory(String fileName){
//1.得到文件名的hashCode值
int code = fileName.hashCode();
System.out.println("code:"+code);
//2.算出第一层目录的名称
int first = code % 20;
System.out.println("first:"+first);
//3.算出第二层目录的名称
Random ramdom = new Random(first % 20);
/*
种子的作用:在多处需要创建Random对象(不是使用nextXX()方法)的地方,使用不同的种子可以有效避免产生产生相同随机数
*/
int second = code & ramdom.nextInt(20);
System.out.println("second:"+second);
return first+"/"+second+"/";
}
/**
* 实现ProgressListener监听文件上传进度
*
*/
class MyProgressListener implements ProgressListener{
/**
* 1: 目前上传了多少字节
* 2: 总长度
* 3: 目前正在第几个文件
*/
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("已经上传了"+pBytesRead+"字节,总字节数为"+pContentLength+"字节,现在正在上传第"+pItems+"个文件!");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}