跳至主要内容

[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> 欄位的 namevalue 屬性產生,因此務必要記得填寫 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);