如何用ArrayBuffer构造一个form请求
本文主要介绍form数据的格式以及如何用代码手动构造一个请求。
一、常用的form enctype类型:
- application/x-www-form-urlencoded
form默认的编码方式,会编码特殊文字,也是jq等库ajax提交数据默认的编码格式 - multi/formdata
这种方式可以提交文本+二进制格式 - text/plain
只编码空格符,这种方式不太常用
其中比较复杂的是multi/formdata类型的,可混合提交文本数据与二进制数据(图片、zip等),下面主要介绍一下这种编码的规律以及在js以及nodejs的构造的方法。
二、分析一个multi/formdata的例子
以下是一个formdata的格式(chrome中):
|
|
分析一下这种编码格式的特点:
1、request header里声明Content-Type,并且在其后加上数据分界符:boundary,即:Content-Type:multipart/form-data; boundary=—-WebKitFormBoundary0yB3cIYoABZUBzEm。
boundary的字符应该是随机的,防止提交的数据里有相同字符而影响服务器的数据解析。
2、request body的部分,规律可看下面的图解:
可以看出:
- body里的boundary总比Content-Type声明的boundary前面多两个中划线;
- 而body结束部分的boundary则在后面再加上两个中划线;
- 每行后面都应该有一个换行符『\r\n』,field name行与field值行之间还有一行仅有一个换行符的空白行。
三、如何构造
以上介绍完了multi/formdata的编码结构,下面说说在js里面是怎么构造的这样的一个请求的。
有同学问了,为啥不用new FormData()直接构造数据呢?嗯。。。
1)第一种情况比较简单,就是表单字段只有文本(数字)的情况。我们可以按照上面的结构,进行简单的字符串拼接,并设置好header,最后xhr.send(form_str);
2)这种是混合了文本与二进制数据的情况,即上图表示的情况,这时候需要结合xhr2、ArrayBuffer、FileReader等api。
请看以下代码以及注释:
|
|
在上面的代码里,由于暂时没能在官方文档找到拷贝或concat整段buffer的方法,所以合并字符数据与图片数据的方法并不十分高效,需要转为普通数组,合并数据后再次转为typed array以获得buffer数据。经过一番转换后计算效率在大文件下或者手机端这种方法的效率还待验证,因为处理普通数组会比直接操作二进制慢不少。
注意,以上代码并不兼容发送中文的情况,大概就是思路用合适字节长度去存储经过encodeURIComponent(或charCode)后的字符,字符code与二进制编码之间的转换这不在本文的讨论范围,有兴趣的同学可参考文后的参考资料。
FormData的api使我们可以处理blob(buffer)、text等数据的提交,平常开发已足够。但是通过了解formdata的数据底层组装方式,或许有助于我们在浏览器端更灵活的处理一些二进制数据、提供一些新思路。
最后再附上nodejs版的构造方式的主要代码:
|
|
有兴趣的同学可以clone这个git地址获取代码:https://github.com/cos2004/formrequest_app.git
代码介绍:
首先npm install,然后npm start启动服务器
http://127.0.0.1:3000/ ,可演示js版的提交,请选择png格式文件
http://127.0.0.1:3000/formdata 演示nodejs版提交,在terminal可以看到输出结果
http://127.0.0.1:3000/submit 表单数据提交接口
参考资料
如何用nodejs通过post发送multipart/form-data类型的http请求