package com.Jsxs.Servlet;
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;
import org.junit.jupiter.api.Test;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
public class Servlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = "文件上传失败!";
//* 判断文件上传的是普通表单还是带文件的表单,
// if (ServletFileUpload.isMultipartContent(req)) {
// System.out.println("失败");
// return;//如果是普通表带那就进入直接返回,否则就不运行
// }
try {
//创建上传文件的保存路径,建议保存为在web-inf的路径下,用户无法直接访问上面的图片
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
// 创建一个文件目录
File file = new File(uploadPath);
// 假如说文件目录不存在情况下,我们就创建
if (!file.exists()) {
file.mkdir(); //创建这个目录
}
//* 缓存,临时文件。假如文件超过了预期的大小,我们就把他放入到一个临时文件中,活几天自动删除或提示用户转存为永久
String tempRealPath = this.getServletContext().getRealPath("/WEB-INF/upload");
// 创建一个文件目录
File tempFile = new File(tempRealPath);
// 假如说文件目录不存在情况下,我们就创建
if (!tempFile.exists()) {
tempFile.mkdir(); //创建这个临时目录
}
//* 处理上传的文件,一般都需要通过流来获取,我们可以使用req.getInputStream(),原生态的上传流获取,十分麻烦
// 但是我们都建议使用Apeache的文件上传组件来实现,common.fileupload,它需要依赖于commons-io组件
// ***************** 1.创建DiskFileItemFactory对象,处理文件上传路径或则大小限制的
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
// 2.通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将她放到临时文件中去
diskFileItemFactory.setSizeThreshold(1024 * 1024); //缓存大小为1MB
// 3.
diskFileItemFactory.setRepository(tempFile); //临时目录的保存目录,需要一个file
/*
ServletFileUpload负责处理上传的文件数据,并将表单中的每个输入项封装成一个Filetem对象,
在使用ServletFileUpload对象解析请求时需要DiskFileletemFactory对象。
所以,我们需要在进行解析工作前构造好DiskFileltemFactory对象,
通过servletFileUpload对象的构造方法或setFileltemFactory()方法
设置ServletFileUpload对象的FileitemFactory属性
*/
// ******************* 4.获取servletFileUpload
ServletFileUpload upload = new ServletFileUpload(diskFileItemFactory);
// 5.监听文件上传的速度
upload.setProgressListener(new ProgressListener() {
public void update(long l, long l1, int i) {
System.out.println("总大小" + l1 + "已上传:" + l);
}
});
// 处理乱码问题
upload.setHeaderEncoding("UTF-8");
// 设置单个文件的最大值
// 1024=1kb*1024=1MB*10=10MB
upload.setSizeMax(1024 * 1024 * 10);
// ******************* 6. 处理上传文件
//(1).把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取
List<FileItem> fileItems = upload.parseRequest(req);
for (FileItem fileItem : fileItems) {
// 判断上传的文件是普通的表单还是带文件的表单
if (fileItem.isFormField()) { //假如说普通的表单
// 判断上传的文件是普通的表单还是带文件的表单
String fieldName = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
System.out.println(fieldName + ":" + value);
} else { //假如是文件
//==================处理文件================//
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名是:"+uploadFileName);
//可能存在文件名不合法的情况
if (uploadFileName.trim().equals("") || uploadFileName == null) {
continue;
}
//获得上传的文件名 /imges/girl.jpg
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//获得文件的后缀名
String fileName_End = uploadFileName.substring(uploadFileName.lastIndexOf(".")+ 1);
System.out.println("文件信息【件名:"+fileName+"--->文件类型"+fileName_End+"】");
/*
如果文件后缀名fileName_End 不是我们所需要的
就直接return,不处理,告诉用户文件类型不对
*/
//可以使用UUID(唯一识别的通用码),保证文件名唯一
//UUID.randomUUID(),随机生成一个唯一识别的通用码;
//网络传输中的东西,都需要序列化
//POJO,实体类,如果想要在多个电脑上运行,需要传输====》需要把对象都序列化
String uuidPath = UUID.randomUUID().toString();
//==================存放地址================//
//存到哪? :uploadPath--->创建的文件目录
// 文件真实存在的路径:realPathFile
String realPath = uploadPath + "/" + uuidPath;
//给每个文件创建一个对应的文件夹
File realPathFile = new File(realPath);
if (!realPathFile.exists()) { //假如说不存在就创建
realPathFile.mkdir();
}
//==================文件传输================//
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
//realpath=真实的文件夹
//差一个文件,加上输出文件的名字+"/+uuidPath"
FileOutputStream fileOutputStream = new FileOutputStream(realPath + "/" + fileName);
//创建一个缓冲区
byte[] bytes = new byte[1024 * 1024];
//判断是否读取完毕
int len = 0;
//如果大于0说明还存在数
while ((len = inputStream.read(bytes)) > 0) {
fileOutputStream.write(bytes, 0, len);
}
//关闭流
fileOutputStream.close();
inputStream.close();
msg = "文件上传成功!";
fileItem.delete(); //上传成功,清楚临时文件
}
}
req.setAttribute("msg",msg);
req.getRequestDispatcher("info.jsp").forward(req,resp);
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}