当前位置:网站首页>原生Servlet - 文件的Upload&Download
原生Servlet - 文件的Upload&Download
2022-06-12 18:52:00 【苏瞳呐】
文件的上传和下载
1. 文件上传细节
要有一个 form 标签,method-post请求 (因为get有长度限制)
form标签的属性
encType值必须为 multipart/form-data表示提交的数据以多端(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
在 form 标签中使用
input type="file"添加上传的文件编写服务器代码 (Servlet接收),接受处理上传的数据
文件上传http请求信息:
请求头:Content-Type: multipart/form-data; boundary=------WebKitFormBoundaryCd3g75eOt35olUs7
解析:
Content-Type表示提交的数据类型multipart/form-data表示以流的形式分段提交服务器boundary表示每段数据的分隔符,值:----WebKitFormBoundarylXiF4fEzpo9c8L4p是浏览器每次随机生成的,它就是每段数据的分界符。在每段里面 第一行是对表单项的描述,然后有个空行,下面是提交的值。
请求体:
------WebKitFormBoundaryCd3g75eOt35olUs7
Content-Disposition: form-data; name="username"
zhu
------WebKitFormBoundaryCd3g75eOt35olUs7
Content-Disposition: form-data; name="photo"; filename="head.jpg"
Content-Type: image/jpeg
文件的信息(很长这里省略了)
------WebKitFormBoundaryCd3g75eOt35olUs7--
因为客户端是以按流的方式提交是,所以我们要按流的方式获取,不能这样: req.getParameter("username");
正确用法:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("上传成功");
ServletInputStream inputStream = req.getInputStream(); // 先得到 字节输入流
byte[] buffer = new byte[1024]; // 缓冲区
int readCount = 0;
while ((readCount = inputStream.read(buffer)) != -1) {
// 打印出来的就是上面全部的请求体
System.out.println(new String(buffer, 0, readCount));
}
}
2. 文件上传
这种文件上传(常用)有很多第三方提供好的API我们使用进行了,可以帮我们对收到的数据进行解析。
例如:commons-fileupload-1.2.1.jar (依赖于 commons-io-1.4.jar)
导入两个jar包
解析
关键的类:
ServletFileUpload类:用于解析上传的数据FileItem类:每一个表单项
//ServletFileUpload中的方法
// 判断当前上传的数据是否是多端的格式,不是解析不了
public boolean ServletFileUpload.isMultipartContent(HttpServletRequest req)
// 解析上传的数据,FileItem表示每一个表单项
public List<FileItem> parseRequest(HttpServletRequest req)
//FileItem中方法
// 判断当前这个表单项是普通的表单项还是文件上传的类型,true表示普通的
public boolean isFormField()
// 获取表单项name属性值
public String getFieldName()
// 获取当前表单项的值
public String getString() // 可传入字符集,防止乱码,一开始req.setCharacterEncoding("UTF-8");也行
// 获取上传的文件名
public String getName()
// 将上传的文件写道 参数file所指向的磁盘位置
public void write(File file)
Servlet上传文件示例:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8"); // 防止乱码
resp.setContentType("text/html; charset=utf-8");
String savePath = getServletContext().getRealPath("/WEB-INF/uploadFile"); //保存的路径
// 首先判断上传的数据是否是多段的数据
if (ServletFileUpload.isMultipartContent(req)) {
FileItemFactory fileItemFactory = new DiskFileItemFactory(); // 创建FileItemFactory工厂的实现类,
// 创建用于解析上传数据的工具类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
List<FileItem> list = servletFileUpload.parseRequest(req); // 解析,得到每一个表单项
for (FileItem fileItem : list) {
if (fileItem.isFormField()) {
// 普通表单项
System.out.print("表单项的name属性值:" + fileItem.getFieldName());
System.out.println(" 表单项的value:" + fileItem.getString("UTF-8"));
} else {
// 文件类型
System.out.print("文件的name属性值:" + fileItem.getFieldName());
System.out.println(" 上传的文件名:" + fileItem.getName());
// 一般会保存到用户访问不能直接访问的目录下 File.separator是系统默认路径分隔符,win下是 /
// (下面这是保存到了部署的真是目录下,保存到了服务器中)
// 可以用UUID保证文件名的唯一性,防止文件覆盖。
// 防止单个目录文件过多影响读写速度,还可以使用目录生成算法分散储存
fileItem.write(new File(savePath + File.separator + fileItem.getName()));
//fileItem.delete(); //关闭资源
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 文件下载
客户端 ->(发送请求告诉服务器我要下载什么文件) -> 服务器
服务器干的内容:
获取要下载的文件名
读取要下载的文件内容
通过响应头告诉客户端返回的数据类型是什么 (和要下载的类型一致)
告诉的客户端收到的数据是用于下载使用(还是用响应头设置)
把下载的的文件内容回传给客户端下载
这个也能用 commons-io-1.4.jar 的IOUtils 类:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8"); // 防止乱码
resp.setCharacterEncoding("UTF-8");
//1.获取要下载的文件名路径名,并通过ServletContext读取读取文件
String downloadFileName = "head.jpg"; // 我们这里写死了
ServletContext servletContext = getServletContext();
String savePath = servletContext.getRealPath("/WEB-INF/upload"); //以前上传文件保存的目录
String downloadPath = savePath + File.separator + downloadFileName;
//2.告诉客户端返回的类型
String downloadType = servletContext.getMimeType(downloadPath); //获取要下载文件的类型 (这个是image/jpeg)
resp.setContentType(downloadType); // (和要下载的类型一样)
//3.告诉客户端收到的数据是用于下载的,不是直接显示在页面的
// Content-Disposition表示收到的数据怎么处理,attachment表示附件下载使用,filename表示下载文件的名字
// filename名可以不和本地的名字一样,当有中文时会乱码,因为http协议设置的的时候不支持中文,需要进行url编码
/resp.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
resp.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(downloadFileName, "UTF-8"));
InputStream resourceAsStream = servletContext.getResourceAsStream(downloadPath);
// getResourceAsStream() 传入文件路径,读取文件!!!!!!!!!!!!!
// 4.commons-io-1.4.jar中有IOUtils我们可以直接用,不用自己read() write()了
ServletOutputStream outputStream = resp.getOutputStream(); // 获取响应的输出流
IOUtils.copy(resourceAsStream, outputStream);
// 读取输入流的信息复制给输出流,输出给客户端,传入一个输入流和输出流 (字节字符流都行)
}
边栏推荐
- Leetcode topic [string]-541- reverse string II
- Have a meal, dry pot, fat intestines + palm treasure!
- Two months later, my second listing anniversary [June 2, 2022]
- tarfile解压嵌套tar
- 基于Halcon的矩形卡片【手动绘制ROI】的自由测量
- Delivery lead time lightweight estimation practice - Notes
- leetcode:5289. Distribute cookies fairly [see data range + DFS pruning]
- Uniapp uses the Ali Icon
- 基于FPGA的VGA协议实现
- How to download Vega in China
猜你喜欢

no available service ‘null‘ found, please make sure registry config correct

A fruitful afternoon

Kali2022 how to install w3af

Go init initialization function
![[blockbuster release] ant dynamic card, enabling the app home page to realize agile update](/img/65/5ed80090f4d0ee92b01888eb496528.jpg)
[blockbuster release] ant dynamic card, enabling the app home page to realize agile update

快速复制浏览器F12中的请求到Postman/或者生成相关语言的对应代码

OpenGL shadow implementation (hard shadow)

美团获得小样本学习榜单FewCLUE第一!Prompt Learning+自训练实战

leetcode:6094. 公司命名【分组枚举 + 不能重复用set交集 + product笛卡儿积(repeat表示长度)】

no available service ‘null‘ found, please make sure registry config correct
随机推荐
liunx部署Seata(Nacos版)
Research Report on the overall scale, major manufacturers, major regions, products and applications of Electric Screwdrivers in the global market in 2022
看不懂Kotlin源码?从Contracts 函数说起~
Leetcode 416. 分割等和子集
Leetcode 494. 目标和
Experiment 10 Bezier curve generation - experiment improvement - control point generation of B-spline curve
Have a meal, dry pot, fat intestines + palm treasure!
Order allocation strategy for instant delivery: from modeling and Optimization - Notes
io.seata.common.exception.FrameworkException: can not connect to services-server.
观察网站的页面
Leetcode topic [string] -151- flip words in string
一种灵活注入 Istio Sidecar 的方案探索
io. seata. common. exception. FrameworkException: can not connect to services-server.
Leetcode 1049. Weight of the last stone II
Review of MySQL (VI): usage of Union and limit
wireshark基本使用命令
How to break the black screen after cleaning the dust and applying silicone grease on the laptop?
leetcode:6096. Success logarithm of spells and potions [sort + dichotomy]
MySQL数据库(28):变量 variables
Partial scratch and corrosion detection of bolts and screws based on Halcon