javascript,form表單的進階學習
前言
在上一篇文章 由form表單來說說前後台資料之間的交互 講解了一些瀏覽器和伺服器在表單之間的聯繫,貌似感覺已經是掌握了form表單,但現實是殘酷的,在最近的一個專案中才發現form表單還有一個大塊知識,在上篇文章只是點了一下的。這塊內容用的地方還蠻多的,就是文件上傳。
1、FormData
上篇文章 中提到組織表單的方法是使用jquery的serializeArray 函數, 但是這個方法對於input[type="file"] 是無效的,也就是說它無法將檔案的內容整合到form表單中去,相關問題可以參考jquery的官方issue:https://bugs.jquery.com/ticket/2656。 其中的解釋是:
The serialize method can't get the contents of the file so I don't understand why it would need to serialize the file form field. You'd have to use one of the Aloadx File one of the pjalugins one of the pupload get the contents via AJAX.
那麼我們是否可以不使用插件來取得提交的表單呢? of course!
1.1、FormData的作用
這就是我們要介紹的 FormData 。根據 FormData 的MDN解釋:
FormData介面提供了一種簡單的方式去建構鍵值對來表示它們的欄位和值,並且可以很容易地透過`XMLHttpRequest.send()`傳送給伺服器。它使用了和表單的編碼類型設定為`multipart/form-data`一樣的格式。
FormData物件可以使用`for...of`的形式來遍歷而不是使用`entries()`:`for (var p of myFormData)`等價於` for (var p of myFormData.entries()) `
這樣的解釋讓我至少明白了兩點:
FormData可以用來處理帶有multipart/form-data 編碼類型的表單,一般都是帶有input[type="file"]的表單;
FormData裡面欄位的檢查可以透過for...in 檢查。 ( 這個物件在瀏覽器中用console.log是印不出來的)
那麼就有童鞋一定會問:
使用FormData來提交不帶有input[type="file"] 類型的
使用FormData來提交不帶有input[type="file"] 類型的表單不可以嗎?
使用FormData來提交不帶有 input[type="file"] 類型的表單但是使用編碼類型為 x-www-form-urlencoded 又會怎麼樣呢?
那麼我們使用demo來解釋這兩個問題:
可以的,此時編碼類型是multipart/form-data ,也即是表單的提交方式大致會是這樣的: 🀜〜〜〜〜〜〜〜〜〜〜〜〜〜這種編碼類型的表單與眾不同的。伺服器端如果使用使用express4以上的版本的話需要安裝額外的middleware來處理這類型的請求,否則你會在 req.body 、 req.param 、 req.query 中沒有發現任何你的表單資料。這些後面會講。那麼為什麼我們依然不提倡使用這種方法來提交那些簡單的表單(大部分網站都是如此):
你肯定發現了我們提交的表單就是簡簡單單幾個字符,但是加上那些boundary之後造成表單資料變大了,也就是說即使是最有效率的二進位編碼也比我們直接將表單資料寫到MIME頭部花的時間來得長!
Tips:但是x-www-form-urlencoded 處理那些不是字母數字的時候便顯得有些吃力了,因為瀏覽器都會將那些非字母數字的轉譯為%HH ,也就是說每一個非字母數字都會由3個位元組來替換,這對於表單很長的時候便很不友善了,於是才有了multipart/form-data 的出現。
回答第二個問題,如果是那樣的話,那麼我們在服務端(express4)中就可以看到req.body :
{ '------WebKitFormBoundary5Kj2oSfHZKrZjjjsx; ': '"user"rnrnddrn------WebKitFormBoundary5Kj2oSfHZKrZjYjsrnContent-Disposition: form-data; name="email"rnrndddrn------WebKitFormBoundary5Kj2oSfHZKrZjrndddrn------WebKitFormBoundary5Kj2oSfHZKrZjrndddrn------WebKitFormBoundary5Kj2oSfH伺服器如何解析呢? ? ?這純粹給自己添堵。
如果不使用FormData的haunted也是可以提交的,可以使用純AJAX來實現,具體細節參考:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using XMLHttpRequest#Submitting forms and uploading_files
1.2、結論
綜上所述,當我們在使用表單的時候含有input[type="file"] 或者含有很多非字母數字的時候,我們需要使用FormData來提交表單,並且編碼類型必須是multipart/form-data 。那麼大致使用的範例是:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>testing form group</title> <script type="text/JavaScript" src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script> <script type="text/JavaScript"> function onSubmit(){ var myForm = document.getElementById('form'); var formData = new FormData(myForm); for (var p of formData){ console.log(p); } $.ajax({ type: 'POST', url: '/get', data: formData, dataType: 'json', processData: false, contentType: false, success: function(data){console.log(data)}, error: function(jqXHR){console.log(jqXHR)}, }) } </script> </head> <body> <form action="" method="post" name='info' id='form'> <input type="text" name="user" /> <input type="text" name="email" /> <input type="file" name="file" /> <input type="file" name="file1" /> </form> <button type="button" name='submit' onclick="onSubmit()">提交</button> </body> </html>
注意
我們的$.ajax中配置了processData: false和contentType: false是為了阻止jquery進一步處理資料:
processData (預設: true) data選項傳遞進來的數據,如果是一個物件(技術上講只要不是字串),都會處理轉換成一個查詢字串,以配合預設內容類型"application/x-www-form-urlencoded"。如果要傳送 DOM 樹資訊或其它不希望轉換的訊息,請設定為 false。
1.3、FormData的API
FormData.append(): 追加一個新的值到已存在的key中或新增一個新的key;
FormData.delete():刪除一個鍵值對FormData.entries(): 傳回一個迭代器以便可以遍歷物件裡面的鍵值對
FormData.keys():傳回一個迭代器以允許遍歷所有鍵值對的鍵FormData.set( ): 修改一個已存在的key中的值或增加新的鍵值對
FormData.values(): 傳回一個迭代器以允許遍歷所有鍵值對的值 2. 關於input[type= "file"]
關於這個類型的input有幾點還是需要提一下,要不下次我自己又忘掉了:
使用multiple 屬性可以一次性選擇多個文件,使用accept屬性可以執行對應的MIME類型。
$(element).files得到的是一個file數組,你可以取得上傳檔案的名字以及上傳檔案的個數: .name 和 length 。
var reg = /^\w+\-v\d+\.{1}\d+\.(json|yaml)$/i; /*Check if the user has not selected uploaded file*/ if ($(Element).val() === ''){ finalRes.delete('file'); } else { var fileCount = $(Element)[0].files.length; for (var i = 0; i < fileCount; i++) { if (reg.test($(Element)[0].files[i].name )){ console.log('match'); }else{ alert('上传的文件名格式不正确'); return; } } }
function clearAllFields(){ $(':input','#project-info') .not(':button, :submit, :reset, :hidden') .val('') .removeAttr('checked') .removeAttr('selected'); }
注意
$(element)表示的是你上傳檔案的input的標籤。
finalRes是你new FormData之後的表單值
3、Express伺服器端的處理
從Express4.x之後,就需要自己編碼很多類型的表單安裝的了。這類的package很多,我自己選擇用了 multiparty 這個middleware。具體的使用方法可以參考官網:https://github.com/expressjs/node-multiparty。
使用事件監聽的形式
使用回調形式
. files中的欄位是根據你在表單中提供的name 的形式來組織的,以第一小節的前端程式碼來說,那麼此時的結果應該是:
router.post('/get', function(req, res, next) { var form = new multiparty.Form(); form.parse(req, function(err, fields, files) { if (fields === undefined || files === undefined){ console.log('client send empty data in posting new project'); return res.status(200).json({err:"请求数据为空,请重新提交", status:'failure'}); } console.log(fields, files); console.log('Upload completed!'); }); });
這時預設檔案已經被上傳到了預設的文件夾,根據官網的解釋,如果沒有在初始化的時候配置uploadDir ,那麼將會上傳到系統的os.tmpdir() 。 至於事件類型的實現方式也是類似的,可以參考其官網給的demo。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
