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);
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章