文件上传
4.5.1 图片上传分析
在添加课程营销信息的表单中,有一个图片上传项
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
4.5.2 文件上传介绍
文件上传的实质:文件的拷贝
- 文件上传:从本地将文件拷贝到服务器磁盘上
- 客户端: 需要编写文件上传表单
- 服务端: 需要编写代码接受上传的 文件
4.5.3 客户端编码
- 文件上传三要素:
- 1.表单提交方式: post (get方式提交有大小限制,post没有)
- 2.表单的enctype属性:必须设置为 multipart/form-data.
- enctype就是encodetype就是编码类型的意思.
- multipart/form-data是多部件文件上传 , 指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。
- 3.表单必须有文件上传项: **file **,必须要有name属性和值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
注意: 默认情况下,表单的enctype的值是application/x-www-form-urlencoded,不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据
- 代码示例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
表单提交必须是POST ,
表单的enctype属性:必须设置为 multipart/form-data.
input的type类型必须指定为: file, 一定要有name属性
--%>
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
<input type="file" name="upload">
<br>
<input type="text" name="name">
<input type="text" name="password">
<input type="submit" value="文件上传">
</form>
</body>
</html>
4.5.4 服务端编码
服务端要接收文件上传的表单数据
1. 上传文件, 抓包分析
使用360浏览器进行抓包,谷歌浏览器不方便查看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
2. 服务端获上传的文件
-
通过request获取请求体的内容
-
解析请求体 多部件上传的特点是,每个input都是一个表单项.
根据分隔符将请求中所有的内容,切割成数组,数组中的每一个元素 都是一个表单项
-
遍历数组,分清楚那个是普通的表单项, 哪个是 文件上传项
如何区分? 判断是否有 filename
-
获取到普通表单项中的内容,通过属性name获取
-
获取文件上传项内容
文件名: filname = aaa.txt
文件内容:
-
使用IO将文件内容,保存到服务器中
4.5.5 FileUpload工具类
1. 导入依赖
FileUpload包可以很容易地将文件上传到你的Web应用程序.
IOUtils封装了Java中io的常见操作,使用十分方便 ,需要下载 commons-io-1.4.jar 包
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
2. FileUpload 核心类介绍
类名 | 介绍 |
---|---|
DiskFileItemFactory | 磁盘文件项工厂, 读取文件时相关的配置,比如: 缓存的大小 , 临时目录的位置 |
ServletFileUplaod | 文件上传的一个核心类 |
FileItem | 代表每一个表单项 |
3. 文件上传的API的详解
- ServletFileUpload
方法 | 说明 |
---|---|
isMultipartContent(request); | 判断是否是一个文件上传的表单 |
parseRequest(request); | 解析request获得表单项的集合 |
setHeaderEncoding(“UTF-8”); | 设置上传的文件名的编码方式 |
- FileItem
方法 | 说明 |
---|---|
isFormField() | 判断是否是普通表单项 |
getFieldName() | 获得表单的name属性值 |
item.getString() | 获得表单的value值 |
getName() | 获得上传文件的名称 |
getInputStream() | 获得上传文件 |
delete() | 删除临时文件 |
4. 文件上传后台代码编写
FileUpload使用步骤:
1、创建磁盘文件项工厂
2、创建文件上传的核心类
3、解析request—获得文件项集合
4、遍历文件项集合
5、判断普通表单项/文件上传项
@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//1.创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.创建文件上传核心类
ServletFileUpload upload = new ServletFileUpload(factory);
//2.1 设置上传文件名的编码
upload.setHeaderEncoding("utf-8");
//2.2 判断表单是否是文件上传表单
boolean multipartContent = upload.isMultipartContent(req);
//2.3 是文件上传表单
if(multipartContent){
//3. 解析request ,获取文件项集合
List<FileItem> list = upload.parseRequest(req);
if(list != null){
//4.遍历获取表单项
for (FileItem item : list) {
//5. 判断是不是一个普通表单项
boolean formField = item.isFormField();
if(formField){
//普通表单项, 当 enctype="multipart/form-data"时, request的getParameter()方法 无法获取参数
String fieldName = item.getFieldName();
String value = item.getString("utf-8");//设置编码
System.out.println(fieldName + "=" + value);
}else{
//文件上传项
//文件名
String fileName = item.getName();
//避免图片名重复 拼接UUID
String newFileName = UUIDUtils.getUUID()+"_"+ fileName;
//获取输入流
InputStream in = item.getInputStream();
//创建输出流 输出到H盘
FileOutputStream fos = new FileOutputStream("H:/upload/" +newFileName);
//使用工具类IOUtils,copy文件
IOUtils.copy(in,fos);
//关闭流
fos.close();
in.close();
}
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
4.5.6 将图片上传到tomcat服务器
1. 将项目部署到webapps
将部署方式改变为 war模式,把项目部署在tomcat的webapps下
- idea中部署项目两种方式
- war模式:将项目以war包的形式上传真实到服务器的webapps目录中;
- war exploded模式:仅仅是目录的映射,就相当于tomcat在项目源文件夹中启动一样;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
2.在webapps中创建upload目录
upload目录专门用来保存上传过来的图片
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
3.修改代码,将图片上传到服务器
- 修改图片的输出路径
- 获取到项目的运行目录信息
- 截取到webapps的 目录路径
- 拼接输出路径,将图片保存到upload
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//1.创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.创建文件上传核心类
ServletFileUpload upload = new ServletFileUpload(factory);
//2.1 设置上传文件名的编码
upload.setHeaderEncoding("utf-8");
//2.2 判断表单是否是文件上传表单
boolean multipartContent = upload.isMultipartContent(req);
//2.3 是文件上传表单
if(multipartContent){
//3. 解析request ,获取文件项集合
List<FileItem> list = upload.parseRequest(req);
if(list != null){
//4.遍历获取表单项
for (FileItem item : list) {
//5. 判断是不是一个普通表单项
boolean formField = item.isFormField();
if(formField){
//普通表单项, 当 enctype="multipart/form-data"时, request的getParameter()方法 无法获取参数
String fieldName = item.getFieldName();
String value = item.getString("utf-8");//设置编码
System.out.println(fieldName + "=" + value);
}else{
//文件上传项
//文件名
String fileName = item.getName();
//避免图片名重复 拼接UUID
String newFileName = UUIDUtils.getUUID()+"_"+ fileName;
//获取上传文件的内容
InputStream in = item.getInputStream();
String path = this.getServletContext().getRealPath("/");
//获取到 webapps路径
String webappsPath = path.substring(0, path.indexOf("lagou_edu_home"));
OutputStream out = new FileOutputStream(webappsPath+"/upload/"+newFileName);
//拷贝文件到服务器
IOUtils.copy(in,out);
out.close();
in.close();
}
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
4. 页面加载图片
将tomcat作为图片服务器使用时,存储上传的图片后,如果想要图片可以访问,需要在idea中进行配置:
- 选择external source —> 找到webapps目录下的的upload文件夹
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
-
上传一张图片到服务器
-
在项目内部页面加载图片
<img src="/upload/abbd99891af442a8a9cb65848744452e_qiyu.jpg">
- 也可以通过HTTP方式访问
http://localhost:8080/upload/abbd99891af442a8a9cb65848744452e_qiyu.jpg