node-formidable源码:原生javascript解析前端传输的FormData

本系列文章是本人学习相关知识时所积累的笔记,以记录自己的学习历程,也为了方便回顾知识;故文章内容较为随意简练,抱着学习目的来的同学务必转移他处,以免我误人子弟~

参考资料:
酷勤网

在Koa和Express中,已经通过node-formidable模块替我们解析好了formdata数据,并分别将文件和表单字段(排除文件)存放在ctx.request.filesctx.request.body对象内。

通过阅读学习了node-formidable后,对解析的过程有了一定的理解,下面我们可以尝试着自己实现较为简单的解析工具

初步认识

  1. 启动项目
    地址:zyhcool: node-formidable
    启动:node myExperiment/server.js
  2. 打开浏览器,输入地址:http://localhost:3000/
  3. 填写完表单和选择文件,点击“upload”
  4. 查看myExperiment/data.txt和控制台输出

结果如下:

// myExperiment/data.txt
------WebKitFormBoundarywA1wAy4KrejGYQgv
Content-Disposition: form-data; name="title"

test
------WebKitFormBoundarywA1wAy4KrejGYQgv
Content-Disposition: form-data; name="upload"; filename="007Tv3Vmly1g7b1zq1xp4j31hc0u0ais.jpg"
Content-Type: image/jpeg

����(一堆乱码,二进制)

......

------WebKitFormBoundarywA1wAy4KrejGYQgv--
1| <Buffer 2d 2d 2d 2d 2d 2d 57 65 62 4b 69 74 46 6f 72 6d 42 6f 75 6e 64 61 72 79 77 41 31 77 41 79 34 4b 72 65 6a 47 59 51 67 76 0d 0a 43 6f 6e 74 65 6e 74 2d ... >
2| <Buffer 40 3d 1b ad a2 61 33 c8 40 20 85 63 9d bf 4e fd 69 5e 29 85 26 43 e0 9f 01 bd 98 6b ed 6a 25 76 91 14 a5 ac 99 21 0f 50 ce 3a 33 0e cb da b2 ff 00 89 ... >
3| <Buffer 3b 4b 8d 56 69 e2 5e 15 e2 b3 0c f2 03 c2 b3 73 f2 8f b6 6a 6f c1 5f aa 12 d2 e6 cd 6d c5 93 79 7f 88 79 12 2c c6 57 0f 26 18 02 e1 40 20 3a e3 9c f2 ... >
4| <Buffer 83 a0 f0 41 b5 f1 9e 93 63 63 70 8e 22 2b 66 f9 b9 b8 c0 f4 ca 8a a7 68 6e c5 bb f7 ac 51 ae ff 00 0e 2c ed 05 a9 f0 cb 45 a9 63 cb b9 7d c2 ea 00 cb ... >
5| <Buffer 28 18 dd 18 3f 7a d5 75 51 6a e8 87 a4 fd 97 19 37 7e 6c 1f 7a 7e 00 aa 0b 77 30 ef 09 fd 69 7e 36 6e 80 47 f7 cd 35 d5 69 73 44 f6 a4 5d d8 be d4 8c ... >
6| <Buffer 7d 36 e0 b4 97 d6 10 34 96 2e 79 63 1a 82 cf 0f be dc 65 97 fa 4a fd 6b 9d 16 c6 58 bc e0 ad e5 82 03 3e de 01 3d 2b 73 c3 1a 15 ee a7 34 af a3 cd 70 ... >

从结果来看,我们能得到一些信息:

  1. ------WebKitFormBoundarywA1wAy4KrejGYQgv是boundary(边界字符串),共有3个,其中头尾分别一个(尾部的boundary多了--);中间那个是titleupload两个字段的boundary
  2. 前端是以二进制流的形式传输formdata数据,而node将其转为Buffer数据
  3. 浏览器分6次才把完整数据全部传到后端
  4. 第一个Buffer开头的6个2d-的ASCII值的16进制,实际上,``转为ASCII值后是'2d', '2d', '2d', '2d', '2d', '2d', '57', '65', '62', '4b', '69', '74', '46', '6f', '72', '6d', '42', '6f', '75', '6e', '64', '61', '72', '79', '77', '41', '31', '77', '41', '79', '34', '4b', '72', '65', '6a', '47', '59', '51', '67', '76' ]
    跟第一个Buffer的值相比,你是不是发现了什么?
    <Buffer 2d 2d 2d 2d 2d 2d 57 65 62 4b 69 74 46 6f 72 6d 42 6f 75 6e 64 61 72 79 77 41 31 77 41 79 34 4b 72 65 6a 47 59 51 67 76 0d 0a 43 6f 6e 74 65 6e 74 2d … >
  5. formidable 就是根据Buffer中的16进制数找到boundary和实际数据所在的位置(索引),并对Buffer进行切割处理,最终拼接成javascript对象(除了文件),并将文件写入磁盘(临时目录);

formidable的解析步骤

  1. 后端处理请求
    // server.js
    let formy = new formidable.IncomingForm();
    formy
         .on('field', function (field, value) {
             console.log(field, value);
         })
         .on('file', function (field, file) {
             console.log(field, file);
         })
         .on("end", function () {
               res.writeHead(200, { "content-type": "application/json" })
               res.end(JSON.stringify({
                   code: 0,
                   data: "good",
               }))
           });
    formy.parse(req);
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章