文件上传、下载

文件上传

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"));
}
posted @   半条咸鱼  阅读(15)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示