[WebAPIs] Form, FormData, 表單取值, AJAX 檔案與資料上傳
keywords: Fetch API
, AJAX
, FormData
FormData Object @ MDN FormData Constructor @ MDN
建立 FormData 物件
// 直接根據網頁上 HTML 的表單元素取得表單資料
var form = document.querySelector('form');
var formData = new FormData(form);
// 如果有需要動態增加表單的資料,
// 不想直接使用 HTML 的表單元素,
// 可以用 append 把欄位灌進去表單中
var formData = new FormData(); // 一開始表單的資料是空的
formData.append('username', Chris); // 增加欄位
formData.append('image', file); // 檔案也可以透過 append 放進來
在前後端分離的網站中,多數的資料都是透過 AJAX 的資料再傳送,透過 FormData
API 可以輕鬆的把表單(form)的資料轉換成可以透過 AJAX 傳送到後端的資料形式。
FormData 的操作與取值方法
當我們取得或建立 FormData 後,有許多方法可以進一步為此表單新增、刪除、取值、判斷該欄位是否存在等方法:
// 新增刪除欄位
FormData.append(<field_name>, <field_value>, [<filename>])
FormData.delete(<field_name>)
FormData.set(<field_name>, <field_value>, [<filename>]) // 已經有的欄位就更新,沒有就新增
// 根據欄位名稱取值
FormData.get(<field_name>) // 取得該欄位的第一個值
FormData.getAll(<field_name>) // 回傳陣列,取得該欄位的所有值
// 取得所有欄位的名稱和值
FormData.entries()
FormData.keys()
FormData.values()
for(let [key, value] of formData.entries()) {
console.log(key+ ', '+ value);
}
// 檢驗表單中是否有該欄位
FormData.has(<field_name>) // 回傳 true 或 false
透過 AJAX 傳送表單資料
- 和傳統的表單一樣,在
<input>
欄位中定義清楚name
屬性 - 監聽
<form>
的submit
事件,記得要preventDefault()
表單才不會直接被瀏覽器送出 - 將
<form>
element 放入new FormData()
中,即可得到該表單的資料 - 透過 AJAX 的方式,把透過
FormData
取得的表單資料直接當成body
的部分直接算出
⚠️ 特別注意:FormData 的資料是根據表單中各
<input>
欄位的name
和value
屬性產生,因此務必要記得填寫 input 中的 name 屬性,<input name="foo" >
。
<!-- form.vue -->
<template>
<form @submit.stop.prevent="handleSubmit">
<div class="form-group">
<label for="name">Name</label>
<input
id="name"
v-model="name"
type="text"
name="name"
class="form-control"
placeholder="Enter Name"
required
/>
</div>
<div class="form-group">
<label for="image">Image</label>
<input id="image" type="file" name="image" accept="image/*" class="form-control-file" />
</div>
</form>
</template>
<script>
export default {
methods: {
handleSubmit(e) {
const form = new FormData(e.target);
this.sendAJAXRequest(form);
},
sendAJAXRequest(form) {
const url = 'http://localhost:3000';
fetch(url, {
method: 'POST',
body: form,
});
},
},
};
</script>
上傳檔案和顯示預覽圖的方式可以進一步參考筆記:[檔案上傳 Input File, File Upload, FileList, and FileAPI](/Users/pjchen/Projects/Notes/source/_posts/WebAPIs/[WEB] 檔案上傳 Input File, File Upload, FileList, and FileAPI.md)
在 Express Server 中處理傳送過來的 FormData
傳送 FormData 資料和一般送出 Form 表單的 Header x-www-form-urlencoded
不同,Form Data 用的是 multipart/form-data
。因此當瀏覽器端傳送的是 FormData 時,Express 的 body-parser 並沒有辦法直接處理 FormData 的資料格式,因此若沒有進行額外的處理,req.body
會空空的。
這時候需要另外安裝其他套件才可以處理 FormData,常見的方式是使用 multer
:
var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var app = express();
// for parsing application/json
app.use(bodyParser.json());
// for parsing x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
//form-urlencoded
// for parsing multipart/form-data
app.use(upload.array());
app.get('/', function (req, res) {
res.render('form');
});
app.post('/', function (req, res) {
console.log(req.body);
res.send('received your request!');
});
app.listen(3000);
- Express Form Data @ Tutorials Point
- [Node.js] express.js + body-parser 處理 multipart/form-data 的解決方案 @ Medium