zoukankan      html  css  js  c++  java
  • JavaWeb上传原理和实现

    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后面的一串随机字符串作为分割标识
    普通表单项:

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

    文件表单项

    //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包

    代码实现

     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();
            }
        }
  • 相关阅读:
    大爽python系列教程 书单
    大爽Python入门教程 71 认识类`class`
    大爽Python入门教程 72 面向对象编程 使用类`class`组织代码
    大爽Python入门教程 75 异常处理 try ... except Exception
    大爽Python入门教程 73 面向对象编程 封装、继承、多态
    大爽Python入门教程 82 Python 库(Library)、包(Package)、模块(Module)
    大爽Python入门练习题 51 实践练习一 简单购物系统(控制台实现)
    大爽Python入门教程 81 导入`import`
    大爽Python入门教程 74 实践演示 控制台版本——简易回合战斗
    大爽Python入门练习题 52 实践练习二 推箱子游戏(控制台实现)
  • 原文地址:https://www.cnblogs.com/aotemanzhifu/p/9192355.html
Copyright © 2011-2022 走看看