前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaWeb上传和下载原理及实现

JavaWeb上传和下载原理及实现

作者头像
秋白
发布2019-02-21 09:52:37
1.3K0
发布2019-02-21 09:52:37
举报
文章被收录于专栏:java小白java小白

1、介绍enctype

  • enctype 属性规定发送到服务器之前应该如何对表单数据进行编码。
  • enctype作用是告知服务器请求正文的MIME类型(请求消息头content-type的作用一样)

1、1 enctype的取值有三种

描述

application/x-www-form-urlencoded

在发送前编码所有字符(默认)

multipart/form-data

不对字符编码。每一个表单项分割为一个部件

text/plain

空格转换为 “+” 加号,但不对特殊字符编码。

1. 当enctype=’application/x-www-form-urlencoded’
这里写图片描述
这里写图片描述
2.当enctype=’multipart/form-data’
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

通过观察发现这个的请求体就发生了变化。这种请求体被称之为多部件请求体。 什么是多部件请求体:就是把每一个表单项分割为一个部件。 以请求头的content-type的boundary后面的一串随机字符串作为分割标识 普通表单项:

代码语言:javascript
复制
//name的意思是文本框里面name的属性值,而admin是我们输入的文本值
Content-Disposition: form-data; name="username"
admin

文件表单项

代码语言:javascript
复制
//filename的意思是:我们上传的文件名称,content-Type的意思是:MIME类型,asdasdas的意思是:文件里面的内容
Content-Disposition: form-data; name="upload"; filename="a.txt"
Content-Type: text/plain
asdasdas
3. 当enctype=’text/plain’
这里写图片描述
这里写图片描述

w3c称:空格会变成”+”加号,但是我这里没有发现,只有当get请求的时候,空格会变成”+”号

这里写图片描述
这里写图片描述

进入正题

完成上传需要满足3个必要的条件

  1. 提供form表单,method必须是post,因为get请求的传输数据一般为2kb,不同浏览器不一样。
  2. form表单属性enctype的必须是multipart/form-data
  3. 提供input type=”file”类的上传输入域 大致实现原理:当enctype的值是multipart/form-data时,浏览器会把每个表单项进行分割,分割成不同的部件,以boundary的值为分割标识,这个标识的字符串是随机生成的,最后一个表单项的分割标识字符串末尾会多两个”- -“,代表结束。服务端用request.getHeader(“content-type”)获取分割字符串,然后进行解析。
这里写图片描述
这里写图片描述

代码实现

一、开发环境搭建

准备两个第三方jar包 commons-io包 commons-upload包

代码实现

代码语言:javascript
复制
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 判断表单的enctype值是不是"multipart/form-data"
        boolean isMultipartContent = ServletFileUpload
                .isMultipartContent(request);
        if (!isMultipartContent) {
            throw new RuntimeException("your form is not multipart/form-data");
        }
        // 创建一个DiskFileItemfactory工厂类
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 创建一个ServletFileUpload核心对象
        ServletFileUpload sfu = new ServletFileUpload(factory);
        // 解析request对象,并得到一个表单项的集合
        try {
            List<FileItem> fileItems = sfu.parseRequest(request);
            // 遍历表单项数据
            for (FileItem fileitem : fileItems) {
                if (fileitem.isFormField()) {
                    // 普通表单项
                    String fieldName = fileitem.getFieldName();
                    String fieldValue = fileitem.getString();
                    System.out.println(fieldName + "=====" + fieldValue);
                } else {
                    //上传表单项
                    //得到文件输入流
                    InputStream is = fileitem.getInputStream();
                    //创建文件存储目录
                    String directoryRealPath = this.getServletContext().getRealPath("WEB-INF/upload");
                    //创建文件路径
                    File storeDirectory = new File(directoryRealPath + File.separator + fileitem.getName());
                    //使用apache commons-io包,将输入流转成文件
                    FileUtils.copyInputStreamToFile(is, storeDirectory);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

下载的必须条件

两个头一个流

content-type

  1. Content-Type是返回消息中非常重要的内容,表示文档内容属于什么MIME类型。
  2. 浏览器会根据Content-Type来决定如何显示返回的消息体内容。
  3. 默认值是text/html
  4. 可以使用request.getServletContext().getMimeType(“文件名”)获取MIME类型。

Content-Disposition

  1. Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。
  2. 默认值是inline,表示在浏览器窗口中打开。
  3. 服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt、jpg等,会直接在浏览器 中显示。
  4. 如果需要提示用户保存,利用Content-Disposition进行一下处理,关键在于一定要加上attachment。 例如:Content-Disposition:attachment;filename=xxx,浏览器就会激活下载框对话框, attachment 表示附件, filname 后面跟随的是显示在下载框中的文件名称。

下载就是向客户端响应字节数据! 将一个文件变成字节数组, 使用 response.getOutputStream() 来响应给浏览器。

实现

代码语言:javascript
复制
    // 下载
    public class DownloadServlet extends HttpServlet{
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException,IOException{
            //根据文件名获取 MIME 类型
            String contentType = this.getServletContext().getMimeType("测试.xls");

            //设置content-Type头
            response.setHeader("Content-Type",contentType);

            //解决下载框为中文名称出现乱码问题
            String fileName;

            //获取用户浏览器
            String agent=request.getHeader("user-agent")

            // 火狐浏览器
            if (agent.contains("Firefox")) { 
                filename = "=?UTF-8?B?"
                        + new BASE64Encoder().encode(filename.getBytes("utf-8"))
                        + "?=";
                filename = filename.replaceAll("\r\n", "");
            // IE及其他浏览器
            } else { 
                filename = URLEncoder.encode(filename, "utf-8");
                filename = filename.replace("+"," ");
            }
            //设置Content-Disposition头
            resp.setHeader("Content-Disposition","attachment; filename=" + filename + "");

            // 输入流
            FileInputStream fis= new FileInputStream("文件路径");
            // 获取输出流
            ServletOutputStream output = response.getOutputStream();
            // 把输入流中的数据写入到输出流中
            byte[] b = new byte[fis.available()];
            fis.read(b);
            //输出
            output .write(b);
            output .flush();
        }
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年06月02日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、介绍enctype
    • 1、1 enctype的取值有三种
      • 1. 当enctype=’application/x-www-form-urlencoded’
      • 2.当enctype=’multipart/form-data’
      • 3. 当enctype=’text/plain’
    • 进入正题
    • 代码实现
      • 一、开发环境搭建
      • 下载的必须条件
        • content-type
          • Content-Disposition
              • 实现
              相关产品与服务
              文件存储
              文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档