文件上传系统
1. 主要需求
- 在用户注册页面,输入用户名,可以选择要上传的文件;
- 点击提交按钮,可以将用户输入的内容和选择的文件保存到服务器上。
2. 技术分析
a. 客户端将文件转为文本
i. 要求
- 表单提交方式必须为 post,即
action="post"
。因为 get 方式的地址栏会有大小的限制。 - 表单的 enctype 属性值必须为 multipart/form-data 多组件表单数据,即
enctype="multipart/form-data"
。 - 必须在表单中提供文件上传项,即
<input type="file" name="pic">
。
ii. 多组件表单数据
- Chrome 无法查看多组件文件上传信息:
- 推荐使用 FireFox 查看:
- 在消息头(请求头)中获得黄金分割线:
enctype="multipart/form-data"
的作用:将请求体通过黄金分割线分割为单项内容:
- 文件上传项中会将上传内容转为文本输出。
b. 服务器将文本转为字节流
i. 获取浏览器上传的数据
- 如果直接通过 Request 对象,效率就会变得非常低,所以可以借用第三方技术来实现:
ii. 处理 IO 流的 3 种方式
- 使用 Apache 提供工具类 commons-fileupload。(这里用到的方式)
- 使用 Servlet3.0 版本。(通过注解实现)
- 使用 SpringMVC 框架。(底层使用了 commons-fileupload)
3. 代码实现
a. 导入文件上传相关 Jar 包
相关 Jar 包已上传至 CSDN:文件上传相关 Jar 包。
b. index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>${NAME}</title>
<script src="${pageContext.request.contextPath}/js/jquery-3.2.1.js"></script>
</head>
<body>
<h3>文件上传</h3>
<form action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username" id="username"><br>
上传图片:<input type="file" name="pic"><br>
<input type = "submit" value="提交表单">
</form>
</body>
</html>
- 访问首页 http://localhost:8080/webappPractice2/,页面显示:
c. 指定服务器保存文件路径
d. UploadServlet 接收文件并保存
i. 步骤分析
- 创建磁盘文件项工厂;
- 创建核心解析对象(依赖工厂对象);
- 解析 Request 对象,返回上传项 List 集合;
- 遍历 List,获取每一个上传项;
- 判断:
- 普通上传项:保存 name 和 value;
- 文件上传项:保存文件名和文本字节输入流到服务器端。
ii. UploadServlet
package com.company;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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;
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// 1.创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2.创建上传解析器对象(依赖工厂对象)
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 3.解析Request请求,返回上传项List集合
List<FileItem> fileItems = fileUpload.parseRequest(request);
// 4.遍历List
for (FileItem fileItem : fileItems) {
// 5.判断是文件项还是普通项
if (fileItem.isFormField()) {// 普通上传项
// 获取name属性名
String name = fileItem.getFieldName();
// 获取value属性值
String value = fileItem.getString();
System.out.println("普通上传项:" + name + "=" + value);
} else {// 文件上传项
// a.获取文件名 Regino.txt
String fileName = fileItem.getName();
// b.获取文件字节输入流
InputStream in = fileItem.getInputStream();
// c.获取文件扩展名
String extName = FileUtil.extName(fileName);
// d.生成随机文件名,解决服务器端保存的文件出现文件名重复问题
fileName = IdUtil.simpleUUID() + "." + extName; // UUID 全球唯一
// 此文件名会保存数据库一份,给用户查询使用...
// 获取upload目录在服务器真实路径
String realPath = request.getServletContext().getRealPath("/upload/");
// 判断此目录是否存在,解决IDEA没有上传空的upload文件夹导致找不到输出目录的问题
File dirFile = new File(realPath);
if (!dirFile.exists()) {
dirFile.mkdirs(); // 如果不存在自己创建
}
// 设置文件字节输出流
FileOutputStream out = new FileOutputStream(realPath + fileName);
// 流的拷贝
IoUtil.copy(in, out);
// 关流
out.close();
in.close();
response.getWriter().write("success");
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
e. 测试
- 上传文件,提交表单:
- 页面显示:
- 控制台显示:
- 上传文件已保存:
原文链接:https://qwert.blog.csdn.net/article/details/105781749
转载:https://blog.csdn.net/Regino/article/details/105781749
查看评论