功能扩展:文件上传
需要的插件:
- fastjson-1.2.68.jar : 阿里巴巴JSON工具类
- commons-fileupload-1.4.jar
- commons-io-2.6.jar
代码实现
/**
*
* @program: 功能扩展
* @author: Yao
* @create: 2020-04-23 17:24
**/
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断上传的文件是普通表单还是带文件的表单
if (!ServletFileUpload.isMultipartContent(req)) {
//终止方法运行,说明这是一个普通的表单,直接返回
return;
}
//创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
//创建这个目录
uploadFile.mkdir();
}
//缓存,临时文件
//临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File file = new File(tmpPath);
if (!file.exists()) {
//创建这个临时目录
file.mkdir();
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
//但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,他需要依赖与 commons-io组件;
try {
//1. 创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
DiskFileItemFactory factory = new DiskFileItemFactory();
// //通过这个工程设置一个缓冲区,当上传的文件大于这个缓冲区时,将它放到临时文件中;
// //缓冲区大小为1M
// factory.setSizeThreshold(1024 * 1024);
// //临时目录的保存目录,需要一个File
// factory.setRepository(file);
//2. 获取ServletFileUpload
ServletFileUpload upload = new ServletFileUpload(factory);
// //监听文件上传进度:
// upload.setProgressListener(new ProgressListener() {
// @Override
// //pBytesRead:已经读取到的文件大小
// //pContentLength:文件大小
// public void update(long pBytesRead, long pContentLength, int pItems) {
// System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
// }
// });
//
// //处理乱码问题
// upload.setHeaderEncoding("UTF-8");
// //设置单个文件的最大值
// upload.setFileSizeMax(1024 * 1024 * 10);
// //设置总共能够上传的文件大小
// //1024 = 1kb * 1024 = 1M * 10 = 10M
// upload.setSizeMax(1024 * 1024 * 10);
//3. 处理上传的文件
//把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取
List<FileItem> fileItems = upload.parseRequest(req);
//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("") || uploadFileName == null) {
continue;
}
//获取上传的文件名
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/" + 1));
//获得文件的后缀名
String fileExName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
//如果文件后缀名 fileExName 不是我们需要的
//就直接return
System.out.println("文件信息[件名:"+fileName+"---文件类型"+fileExName);
//UUID:唯一识别的通用码
//UUID.randomUUID():随机生成的唯一识别的通用码
// 网络传输中的东西,都需要序列化
// POJO,实体类,如果想要再多个电脑上运行, 传输==>需要把对象都序列化了
// JNI = Java Native Interface
// implement Serializable: 标记接口,JVM---> Java栈 本地方法栈 native -->C++
String uuidPath = UUID.randomUUID().toString();
//=====================存放地址=====================//
//存到哪儿?uploadPath
//文件的真实存在的路径 realPath
String realPath = uploadPath + "/" + uuidPath;
//给每个文件创建一个对应的文件夹
File realPathFile = new File(realPath);
if (!realPathFile.exists()) {
realPathFile.mkdir();
}
//=====================文件传输=====================//
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
//realPath = 真实的文件夹;
//差了一个文件;加上输出文件的名字+"/"+uuidFileName
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
//创建一个缓冲区
byte[] buffer = new byte[1024 * 1024];
//判断是否读取完毕
int len = 0;
//如果大于0说明还存在数据;
while ((len = inputStream.read(buffer)) > 0) {
fos.write(buffer,0,len);
}
//关闭流
fos.close();
inputStream.close();
//上传成功,清楚临时文件
fileItem.delete();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
需要注意的三个点:
- uuid
- interface Serializable
- native关键字