文件上传-java web
第一步:需要引入两个依赖:common-fileupload和commin-io.
第二步.在web页面中添加上传文件的输入项
1.必须使用<input type="file">,并设置input的name属性.
<input type="file" name="file">
2.form表单的enctype必须设置为multipart/form-data.
enctype="multipart/form-data"
3.form表单的提交方式必须是post.
method="post"
第三步.编写servlet,将用户上传的数据保存到本地硬盘.
1.判断用户提交的是否是带文件的表单,如果是普通的表单中止方法运行,直接返回.
if(!ServletFileUpload.isMultipartContent(request)){
return;
}
2.创建两个路径,一个文件保存的路径,一个是文件保存的临时路径,防止文件过大占用硬盘空间.
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()){
uploadFile.mkdirs();
}
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File file = new File(tmpPath);
if (!file.exists()){
file.mkdirs();
}
3.创建一个DiskFileItempFactory对象,相当于是一个缓冲区,将过大的文件放入临时路径.(将这个过程封装成方法一,参数是:临时路径,返回DiskFileItempFactory对象)
DiskFileItemFactory factory = getDiskFileItemFactory(file);
4.创建并配置一个ServletFileUpload对象,需要用它来解析前端请求.(将这个过程封装成方法二,参数是:DiskFileItempFactory对象,返回值:ServletFileUpload对象)
ServletFileUpload upload = getServletFileUpload(factory);
5.通过ServletFileUpload对象,将前端请求封装成FileItem对象,FileItem对象可以获取一个输入流,将这个流输出到本地磁盘上,就是用户上传的文件(将这个过程封装成方法三,参数是:ServletFileUpload对象,前端请求,文件保存路径,返回值:执行结果)
String message = uploadParseRequest(upload, request, uploadPath);
6.根据执行结果对前端进行反馈,并跳转页面.
if (Objects.equals(message, "文件上传成功!")){
}else {
message = "请上传文件!";
}
request.setAttribute("message",message);
request.getRequestDispatcher("info.jsp").forward(request,response);
方法一
/**
* 上传文件的缓冲区
* @param file 临时文件路径
* @return DiskFileItemFactory对象
*/
public static DiskFileItemFactory getDiskFileItemFactory(File file) {
//创建一个DiskFileItemFactory对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓冲区大小为1M
factory.setSizeThreshold(1024 * 1024);
//设置临时文件的保存路径为方法参数中file
factory.setRepository(file);
//返回设置好的DiskFileItemFactory对象
return factory;
}
方法二
/**
* 对创建的ServletFileUpload对象进行配置
* @param factory 缓存区
* @return 配置好的ServletFileUpload对象
*/
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
//创建ServletFileUpload对象,传入设置好的缓存区对象
ServletFileUpload upload = new ServletFileUpload(factory);
// 监听上传进度
upload.setProgressListener(new ProgressListener() {
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead+",进度:"+((double)pBytesRead/pContentLength)*100+"%");
}
});
// 处理编码,防止乱码
upload.setHeaderEncoding("UTF-8");
// 设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//返回ServletFileUpload对象
return upload;
}
方法三(核心方法)
/**
* 将前端请求中的文件写入本地磁盘
* @param upload ServletFileUpload对象
* @param request 前端请求
* @param uploadPath 本地保存文件的路径
* @return 执行结果
* @throws FileUploadException 文件上传异常
* @throws IOException IO异常
*/
public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath) throws FileUploadException, IOException {
//创建返回结果
String message = "";
//利用ServletFileUpload对象将前端请求解析并封装成FileItem对象,返回一个FileItem对象集
List<FileItem> fileItems = upload.parseRequest(request);
//遍历封装后的FileItem对象
for (FileItem fileItem : fileItems) {
//判断前端提交的表单有没有文件上传
if (fileItem.isFormField()) { //没有文件上传
//getFieldName获取的的是前端表单控件的name;
String name = fileItem.getFieldName();
//处理乱码
String value = fileItem.getString("UTF-8");
System.out.println(name + ": " + value);
} else {// 有文件上传
// ============处理文件名开始==============
// 拿到文件名
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名: " + uploadFileName);
//将文件名前后空格去除后,判断是否为空字符串
if (uploadFileName.trim().equals("")) {
continue;
}
// 获取上传的文件名,将路径去除,只留下 / 后的字符串就是文件自己的名字 例如: C:\Users\lvjianhua\1.jpg
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
// 获得文件的后缀名,将最后一个点后面的字符串获取,来判断文件类型 例如: C:\Users\lvjianhua\1.jpg
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
//如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。
System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]");
// ================处理文件名完毕==============
// ==============处理存放地址开始==============
// 可以使用UID(唯一识别的通用码),保证文件名唯一
// UUID.randomUUID(),这个方法可以随机生一个唯一识别的通用码;
String uuidPath = UUID.randomUUID().toString();
//用刚才随机生成的UUID和文件保存的路径拼接一个新路径,这个路径就是文件最后存储的路径
String realPath = uploadPath + "/" + uuidPath;
//根据这个新路径创建文件夹,每个文件都会有一个单独的文件夹,防止文件重名,发生覆盖,
File realPathFile = new File(realPath);
//判断文件夹是否存在
if (!realPathFile.exists()) {
//不存在就生成一个
realPathFile.mkdir();
}
// ==============存放地址完毕==============
// =============文件传输开始=============
//通过FileItem对象获得文件上传的输入流
InputStream is = fileItem.getInputStream();
//创建输入流,文件路径就是,最终存放地址 + 文件名
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
//创建一个缓冲区
byte[] buffer = new byte[1024 * 1024];
//设置一个int值,来储存读取数据的长度
int len = 0;
// 一边读,一边写,如果读取的数据长度大于0说明还存在数据,就继续输出
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
// 关闭流
fos.close();
is.close();
//执行到此处,说明文件储存成功,给返回结果赋值
message = "文件上传成功!";
//上传成功,清除临时文件
fileItem.delete();
//=============文件传输完毕=============
}
}
//返回执行结果
return message;
}
第四步.查看本地磁盘中前端上传的文件
文件上传的四大注意事项:
- 为保证服务器安全,上传的文件应该放在外界无法直接访问的目录下,比如放在WEB-INF目录下
- 为防止上传的文件发生覆盖,要为每一个上传的文件生成一个唯一的文件名
- 限制上传文件的大小
- 限制上传文件的类型,通过文件的后缀名判断是否合法