• multipart/form-data


    一.什么是multipart/form-data

    首先我们需要明白在html中的enctype属性.
    enctype:规定了form表单在发送到服务器时候编码方式。有如下的三个值。
    application/x-www-form-urlencoded。默认的编码方式。但是在用文本的传输和MP3等大型文件的时候,使用这种编码就显得 效率低下。
    multipart/form-data 。 指定传输数据为二进制类型,比如图片、mp3、文件。
    text/plain。纯文体的传输。空格转换为 “+” 加号,但不对特殊字符编码。

    二.明确在enctype参数为application/x-www-form-urlencoded的时候post和get请求参数和请求体是什么形式的

    2.1 get请求

    请求头:

    GET/www.xxx.com?name=%22hello+world%22&**file=temp.png**&submit=submit HTTP/1.1
    

    因为get请求没有请求体,所有他的所有参数都是在url的后边添加。type=file的表单项只能获取到文件的名字,并不能获取文件的内容。

    2.2 post请求

    请求头:

    POST /www.baidu.com HTTP/1.1
    

    请求体:

    name=%22hello+world%22&file=temp.png&submit=submit
    

    (1)我们可以发现不管是post请求和get请求,他们的参数存在的形式都是不变的,通过key=value的形式存在。
    (2)表单项type=filed只能获取获取文件的名字不能获取文件的内容。

    三. multipart/form-data

    ...
    Content-Type: multipart/form-data; boundary=${boundary}
    
    --${boundary}
    ...
    ...
    
    --${boundary}--
    

    请求内容格式为Content-Type: multipart/form-data,用来指定请求内容的数据编码格式。

    3.1 boundary字符串

    该格式会生成一个boundary字符串来分割请求头与请求体的,具体的是以一个boundary=${boundary}来进行分割。

    1、上面boundary=${boundary}之后就是请求体内容了,
    2、请求体内容各字段之间以--${boundary}来进行分割,
    3、以--${boundary}--来结束请求体内容。

    3.2 get请求 无效

    请求头:

    GET/www.xxx.com?name=%22hello+world%22&file=temp.png&submit=submit HTTP/1.1
    

    get请求和multipart/form-data结合无效,因为文件上传需要请求体

    3.3 post请求:

    请求头:

    POST /www.xxx.com HTTP/1.1
    

    请求体:

    ------WebKitFormBoundaryIZDrYHwuf2VJdpHw
    Content-Disposition: form-data; name="name"
    
    "hello world"
    ------WebKitFormBoundaryIZDrYHwuf2VJdpHw
    Content-Disposition: form-data; name="file"; filename="temp.png"
    Content-Type: image/png
    
    .PNG
    .
    ...
    IHDR...
    ..........Y../..,+|.$aIk.v...G?...P.P,,...m..e.2....v.7.	pHYs...%...%.IR$....|IDAT(.cTT....................:.?.......}.(.Pd`A..V...L...?..#.....4.o..LS.....W.d.?...A8..LS...(.u.......D.b......b.....o&..;..<.1......IEND.B`.
    ------WebKitFormBoundaryIZDrYHwuf2VJdpHw
    Content-Disposition: form-data; name="submit"
    
    submit
    ------WebKitFormBoundaryIZDrYHwuf2VJdpHw--
    

    3.4 多部件请求体

    通过观察发现这个的请求体就发生了变化。这种请求体被称之为多部件请求体
    什么是多部件请求体:就是把每一个表单项分割为一个部件。
    因为表单项分为普通表单项文件表单项,所以说部件也有区别。

    3.4.1 普通表单项:

    • 一个请求头:Content-Disposition: form-data; name=”name”
    • 一个请求体:里面就是我们表单的值”hello world”

    3.4.2 文件表单项:

    • 两个请求头:
      • Content-Disposition: form-data; name="file";
      • filename="temp.png"
    • 一个请求体:
    .PNG
    .
    ...
    IHDR...
    ..........Y../..,+|.$aIk.v...G?...P.P,,...m..e.2....v.7.	pHYs...%...%.IR$....|IDAT(.cTT....................:.?.......}.(.Pd`A..V...L...?..#.....4.o..LS.....W.d.?...A8..LS...(.u.......D.b......b.....o&..;..<.1......IEND.B`.
    ------WebKitFormBoundaryIZDrYHwuf2VJdpHw
    Content-Disposition: form-data; name="submit"
    
    submit
    ------WebKitFormBoundaryIZDrYHwuf2VJdpHw--
    

    3.5 FormData对象

    XMLHttpRequest Level 2添加了一个新的接口FormData。利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单"。

    var formData = new FormData();
    formData.append("username", "Groucho");
    formData.append("accountnum", 123456);
    fetch('/users', {
      method: 'POST',
      body: formData
    })
    

    上面创建了一个FormData对象,通过fetch进行ajax请求时,会自动为其将其转为form-data格式,无需手动添加格式。

    3.6 对象转FormData对象

    对于FormDat对象,像上面那种形式可以直接添加参数比较方便,但是对于对象或者嵌套对象:

     let userObj = {userName: ’xxx', age: '21'};
     formData.append('user', userObj);
    

    上面形式添加formData参数user,并不会获取到其真正的内容,而是返回userObj的Object.prototype.toString.call(userObj)的值作为user字段的值。

    ------WebKitFormBoundaryyb1zYhTI38xpQxBK
    Content-Disposition: form-data; name="user"
    
    [object Object]
    

    遗憾的是,FormData对象没有像JSON.stringify那样的方法能批量将对象形式转换为对应的形式,formData而言是将对象的key转换为正确formData请求参数字段名,例如如下对象:

    var obj = {
        a: '2',
        b: {c: 'test'},
        c: [
            {id: 1, name: 'xx'},
            {id:2 ,name: 'yy', info: {d: 4} }
        ]
    }
    

    这样转换为FormData对象时,其对应的key应该是下面这样的:

    a: 2
    b[c]: test
    c[][id]: 1
    c[][name]: xx
    c[][id]: 2
    c[][name]: yy
    c[][info][d]:4
    

    这样,就需要我们自己手动来实现一个转换数据函数,具体代码如下:

    function objectToFormData (obj, form, namespace) {
      const fd = form || new FormData();
      let formKey;
    
      for(var property in obj) {
          if(obj.hasOwnProperty(property)) {
            let key = Array.isArray(obj) ? '[]' : `[${property}]`;
            if(namespace) {
              formKey = namespace + key;
            } else {
              formKey = property;
            }
    
            // if the property is an object, but not a File, use recursivity.
            if(typeof obj[property] === 'object' && !(obj[property] instanceof File)) {
              objectToFormData(obj[property], fd, formKey);
            } else {
    
              // if it's a string or a File object
              fd.append(formKey, obj[property]);
            }
    
          }
        }
    
      return fd;
    
    }
    

    这样,就可以将对象转化为对应的formData的格式了。

  • 相关阅读:
    python 可迭代对象与迭代器
    linux与linux远程桌面
    get return value of python in shell
    python反汇编函数字节码
    celery.backends.base.NotRegistered.
    supervisor process management
    Kafka的Log存储解析
    kafka config
    Chanel
    PowerPoint的公式
  • 原文地址:https://www.cnblogs.com/qiqi715/p/10170100.html
Copyright © 2020-2023  润新知