1. jsp
<%@ page language="java" contentType="text/html" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="FileUploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="name"><br>
文件1:<input type="file" name="f1"><br>
文件2:<input type="file" name="f2"><br>
<input type="submit" value="提交">
</form> </body>
</html>
2. java
文件上传的前提
1.form表单的method必须是post
2.form表单的enctype必须是multipart/form-data 以二进制字节流
进行提交 传统接收参数的方式无效
DiskFileItemFactory:环境
void setSizeThreshold(int sizeThreshold)
设置缓冲区大小,默认10KB 超出将使用临时文件上传
void setRepository(File repository)
设置临时文件路径
ServletFileUpload:核心操作类
public void setSizeMax(long sizeMax)设置总文件的大小
public void setFileSizeMax(long fileSizeMax):设置单个文件的大小
public List parseRequest(javax.servlet.http.HttpServletRequest req)
解析请求正文内容
public static boolean isMultipartContent(HttpServletRequest req)//判断enctype
FileItem:输入域
boolean isFormField():判断是否是普通字段
String getName():获取上传文件名
String getFieldName():获取普通字段的字段名
String getString():获取普通字段的值
String getContentType() 获得文件类型
InputStream getInputStream()以流的形式返回上传文件的主体内容
void delete()删除临时文件
文件上传中需要注意的问题
1.保证安全
上传文件放在WEB-INF目录中
2.中文乱码问题
普通字段乱码
String fieldValue = item.getString("GBK");
文件名乱码
request.setCharacterEncoding("GBK");
3.重名文件覆盖
1.UUID
2.使用文件上传日期分类存储
3.System.currentMillions()
4.限制文件上传类型
1.endsWith("")这种方式不可取
2.判断其mime类型 getContentType()
5.限制用户上传文件的大小
1.限制单个上传文件的大小
upload.setFileSizeMax(4*1024*1024);
2.限制总文件大小
upload.setSizeMax()
6.临时文件
item.delete();
7.多个文件上传时,没有上传内容的问题
if(fileName==null||"".equals(fileName.trim())){
continue;
}
8.上传进度检测
upload.setProgressListener(new ProgressListener(){
参数一:已上传的字节数
参数二:总字节数
参数三:第几项
@Override
public void update(long arg0, long arg1, int arg2) {
// TODO Auto-generated method stub
System.out.println(arg0+" "+arg1+" "+arg2);
} });
package cn.gs.ly; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload; public class FileUploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//得到上传文件的保存目录。 将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String realPath = this.getServletContext().getRealPath("/upload");// /WEB-INF/files
System.out.println("文件存放位置:"+realPath);
//设置临时目录。 上传文件大于缓冲区则先放于临时目录中
String tempPath = "E:\\tempPath";
System.out.println("临时文件存放位置:"+tempPath); //判断存放上传文件的目录是否存在(不存在则创建)
File f = new File(realPath);
if(!f.exists()&&!f.isDirectory()){
System.out.println("目录或文件不存在! 创建目标目录。");
f.mkdir();
}
//判断临时目录是否存在(不存在则创建)
File f1 = new File(tempPath);
if(!f1.isDirectory()){
System.out.println("临时文件目录不存在! 创建临时文件目录");
f1.mkdir();
} /**
* 使用Apache文件上传组件处理文件上传步骤:
*
* */
//1、设置环境:创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory(); //设置上传文件的临时目录
factory.setRepository(f1); //2、核心操作类:创建一个文件上传解析器。
ServletFileUpload upload = new ServletFileUpload(factory);
//解决上传"文件名"的中文乱码
upload.setHeaderEncoding("UTF-8"); //3、判断enctype:判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(req)){
System.out.println("不是上传文件,终止");
//按照传统方式获取数据
return;
} //==获取输入项==
// //限制单个上传文件大小(5M)
// upload.setFileSizeMax(1024*1024*4);
// //限制总上传文件大小(10M)
// upload.setSizeMax(1024*1024*6); //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> items =upload.parseRequest(req);
for(FileItem item:items){
//如果fileitem中封装的是普通输入项的数据(输出名、值)
if(item.isFormField()){
String filedName = item.getFieldName();//普通输入项数据的名
//解决普通输入项的数据的中文乱码问题
String filedValue = item.getString("UTF-8");//普通输入项的值
System.out.println("普通字段:"+filedName+"=="+filedValue);
}else{
//如果fileitem中封装的是上传文件,得到上传的文件名称,
String fileName = item.getName();//上传文件的名
//多个文件上传输入框有空 的 异常处理
if(fileName==null||"".equals(fileName.trim())){ //去空格是否为空
continue;// 为空,跳过当次循环, 第一个没输入则跳过可以继续输入第二个
} //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理上传文件的文件名的路径,截取字符串只保留文件名部分。//截取留最后一个"\"之后,+1截取向右移一位("\a.txt"-->"a.txt")
fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
//拼接上传路径。存放路径+上传的文件名
String filePath = realPath+"\\"+fileName;
//构建输入输出流
InputStream in = item.getInputStream(); //获取item中的上传文件的输入流
OutputStream out = new FileOutputStream(filePath); //创建一个文件输出流 //创建一个缓冲区
byte b[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int len = -1;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))!=-1就表示in里面还有数据
while((len=in.read(b))!=-1){ //没数据了返回-1
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath+"\\"+filename)当中
out.write(b, 0, len);
}
//关闭流
out.close();
in.close();
//删除临时文件
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
item.delete();//删除处理文件上传时生成的临时文件
System.out.println("文件上传成功");
}
}
} catch (FileUploadException e) {
//e.printStackTrace();
throw new RuntimeException("服务器繁忙,文件上传失败");
}
} @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}