文件上传、下载
文件上传
1、设置表单标签
<form action="https://localhost:8080" method="post" enctype="multipart/form-data">
<input type="file"/>
<input type="submit"/>
</form>
(1)enctype 属性:规定在将表单数据发送到服务器之前如何对其进行编码
(2)只有 method="post" 时才使用 enctype 属性
值 | 描述 |
---|---|
application/x-www-form-urlencoded | 默认。在发送前对所有字符进行编码(将空格转换为 "+" 符号,特殊字符转换为 ASCII HEX 值) |
multipart/form-data | 不对字符编码。当使用有文件上传控件的表单时,该值是必需的 |
text/plain | 将空格转换为 "+" 符号,但不编码特殊字符 |
2、encType="multipart/form-data" 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
文件上传的 HTTP 协议内容(示例)
1、请求行
2、请求头
(1)Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycl2joVsAFxzitHaW
(2)boundary 表示每段数据的分隔符
(3)WebKitFormBoundarycl2joVsAFxzitHaW 由浏览器每次都随机生成,是每段数据的分界符
3、空行
4、请求体
(1)-----WebKitFormBoundarycl2joVsAFxzitHaW 表示一段数据的开始
(2)Content-Disposition: form-datas name="username"
(3)空行
(4)当前表单项的值
(5)-----WebKitFormBoundarycl2joVsAFxzitHaW 表示另一段数据的开始
(6)Content-Disposition: form-data; name="photo"; filename="d.jpg"
(7)Content-Type: image/jpeg
(8)空行
(9)上传文件的数据
(10)-----WebKitFormBoundarycl2joVsAFxzitHaW-- 多了两个减号的分隔符,表示数据的结束标记
commons-fileupload.jar、commons-io.jar
1、ServletFileUpload 类,解析上传的数据
(1)判断当前上传数据格式是否为多段格式
public static final boolean isMultipartContent(HttpServletRequest request)
(2)解析上传数据
public List<FileItem> parseRequest(HttpServletRequest request) throws FileUploadException
2、Fileltem 接口,表示每一个表单项
(1)判断当前表单项,是普通的表单项 / 上传的文件类型:true 表示普通类型的表单项;false 表示上传的文件类型
boolean isFormField();
(2)获取表单项 name 属性值
String getFieldName();
(3)获取当前表单项的值
String getString();
String getString(String encoding) throws UnsupportedEncodingException;
(4)获取上传的文件名
String getName();
(5)将上传的文件写到 file 所指向的硬盘位置
void write(File file) throws Exception;
接收上传文件请求
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
//判断是否为多段数据,只有多段数据才是上传数据
if (ServletFileUpload.isMultipartContent(req)) {
//创建FileItemFactory工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
//创建解析上传数据ServletFileUpload工具类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
//解析上传数据,得到每一个表单项FileItem
List<FileItem> fileItems = servletFileUpload.parseRequest(req);
//循环判断每一个表单项,普通类型 / 上传文件
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {
//普通表单项
System.out.println(fileItem.getFieldName());
//解决中文乱码
System.out.println(fileItem.getString("UTF-8"));
} else {
//上传文件
System.out.println(fileItem.getFieldName());
System.out.println(fileItem.getName());
//写入磁盘
fileItem.write(new File("d:\\" + fileItem.getName()));
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
文件下载响应(示例)
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
//获取下载文件名
String downloadFileName = req.getParameter("downloadFileName");
//通过ServletContext对象,获取下载文件内容
ServletContext servletContext = getServletContext();
//获取下载文件类型
String mimeType = servletContext.getMimeType("/download/" + downloadFileName);
//回传前
//通过响应头告知客户端返回数据类型
resp.setContentType(mimeType);
//通过响应头告知客户端收到数据用于下载
//Content-Disposition 响应头,表示如何处理接收数据
//attachment 表示附件,表示下载使用
//filename= 表示指定下载文件名
//URL编码把中文转换为%xxx%xxx的形式,解决中文乱码
resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(downloadFileName, "UTF-8"));
//以流形式返回下载文件
InputStream resourceAsStream = servletContext.getResourceAsStream("/download/" + downloadFileName);
//获取响应输出流
ServletOutputStream outputStream = resp.getOutputStream();
//读取输出流中全部数据,复制到输出流,输出到客户端
IOUtils.copy(resourceAsStream, outputStream);
}
1、解决中文乱码
(1) URLEncoder
(2)Base64
/*
=? 表示编码内容开始
B 表示 BASE64 编码
?= 表示编码内容结束
*/
resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + new BASE64Encoder().encode(downLoadName.getBytes("UTF-8")) + "?=");
String content = "待编码内容";
//创建Base64编码器
BASE64Encoder base64Encoder = new BASE64Encoder();
//执行Base64编码操作
String encode = base64Encoder.encode(content.getBytes("UTF-8"));
//创建Base64解码器
BASE64Decoder base64Decoder = new BASE64Decoder();
//执行Base64解码操作
byte[] bytes = base64Decoder.decodeBuffer(encode);
String s = new String(bytes, "UTF-8");
(3)通过 User-Agent 使用不同方式
if (req.getHeader("User-Agent").contains("Firefox")) {
resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + new BASE64Encoder().encode(downLoadName.getBytes("UTF-8")) + "?=");
} else {
resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(downloadFileName, "UTF-8"));
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战