Tato kapitola je o odesílání formulářů HTML:se soubory nebo bez nich, s dalšími poli atd.
S tím mohou pomoci objekty FormData. Jak jste možná uhodli, je to objekt reprezentující data formuláře HTML.
Konstruktor je:
let formData = new FormData([form]);
Pokud HTML form
prvek, automaticky zachytí jeho pole.
Zvláštní věc na FormData
jsou síťové metody, jako je fetch
, může přijmout FormData
objekt jako tělo. Je zakódováno a odesláno s Content-Type: multipart/form-data
.
Z pohledu serveru to vypadá jako obvyklé odeslání formuláře.
Odeslání jednoduchého formuláře
Nejprve odešleme jednoduchý formulář.
Jak vidíte, je to téměř jednodílné:
<form id="formElem">
<input type="text" name="name" value="John">
<input type="text" name="surname" value="Smith">
<input type="submit">
</form>
<script>
formElem.onsubmit = async (e) => {
e.preventDefault();
let response = await fetch('/article/formdata/post/user', {
method: 'POST',
body: new FormData(formElem)
});
let result = await response.json();
alert(result.message);
};
</script>
V tomto příkladu není uveden kód serveru, protože je mimo náš rozsah. Server přijme požadavek POST a odpoví „Uživatel uložen“.
Metody FormData
Můžeme upravit pole v FormData
s metodami:
formData.append(name, value)
– přidejte pole formuláře s danýmname
avalue
,formData.append(name, blob, fileName)
– přidejte pole, jako by to bylo<input type="file">
, třetí argumentfileName
nastavuje název souboru (ne název pole formuláře), jako by to bylo jméno souboru v systému souborů uživatele,formData.delete(name)
– odeberte pole s danýmname
,formData.get(name)
– získat hodnotu pole s danýmname
,formData.has(name)
– pokud existuje pole s danýmname
, vrátítrue
, jinakfalse
Formulář může mít technicky mnoho polí se stejným name
, takže více volání na append
přidejte další pole stejného jména.
Existuje také metoda set
, se stejnou syntaxí jako append
. Rozdíl je v tom, že .set
odstraní všechna pole s daným name
a poté připojí nové pole. Takže zajišťuje, že existuje pouze jedno pole s takovým name
, zbytek je jako append
:
formData.set(name, value)
,formData.set(name, blob, fileName)
.
Také můžeme iterovat přes pole formData pomocí for..of
smyčka:
let formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
// List key/value pairs
for(let [name, value] of formData) {
alert(`${name} = ${value}`); // key1 = value1, then key2 = value2
}
Odeslání formuláře se souborem
Formulář je vždy odeslán jako Content-Type: multipart/form-data
, toto kódování umožňuje posílat soubory. Takže <input type="file">
pole jsou také odeslána, podobně jako při obvyklém odeslání formuláře.
Zde je příklad s takovým formulářem:
<form id="formElem">
<input type="text" name="firstName" value="John">
Picture: <input type="file" name="picture" accept="image/*">
<input type="submit">
</form>
<script>
formElem.onsubmit = async (e) => {
e.preventDefault();
let response = await fetch('/article/formdata/post/user-avatar', {
method: 'POST',
body: new FormData(formElem)
});
let result = await response.json();
alert(result.message);
};
</script>
Odeslání formuláře s daty objektů Blob
Jak jsme viděli v kapitole Načítání, je snadné odesílat dynamicky generovaná binární data, např. obrázek, jako Blob
. Můžeme jej dodat přímo jako fetch
parametr body
.
V praxi je však často vhodné odeslat obrázek nikoli samostatně, ale jako součást formuláře s dalšími poli, jako je „jméno“ a další metadata.
Servery jsou také obvykle vhodnější k přijímání vícedílně zakódovaných formulářů, spíše než nezpracovaných binárních dat.
Tento příklad odešle obrázek z <canvas>
, spolu s některými dalšími poli jako formulář pomocí FormData
:
<body style="margin:0">
<canvas id="canvasElem" width="100" height="80" style="border:1px solid"></canvas>
<input type="button" value="Submit" onclick="submit()">
<script>
canvasElem.onmousemove = function(e) {
let ctx = canvasElem.getContext('2d');
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
};
async function submit() {
let imageBlob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
let formData = new FormData();
formData.append("firstName", "John");
formData.append("image", imageBlob, "image.png");
let response = await fetch('/article/formdata/post/image-form', {
method: 'POST',
body: formData
});
let result = await response.json();
alert(result.message);
}
</script>
</body>
Všimněte si prosím, jak obrázek Blob
je přidáno:
formData.append("image", imageBlob, "image.png");
To je stejné, jako kdyby existovalo <input type="file" name="image">
ve formuláři a návštěvník odeslal soubor s názvem "image.png"
(3. argument) s údaji imageBlob
(2. argument) z jejich souborového systému.
Server čte data formuláře a soubor, jako by šlo o běžné odeslání formuláře.
Shrnutí
Objekty FormData se používají k zachycení formuláře HTML a jeho odeslání pomocí fetch
nebo jinou síťovou metodou.
Můžeme buď vytvořit new FormData(form)
z formuláře HTML nebo vytvořte objekt bez formuláře a poté přidejte pole pomocí metod:
formData.append(name, value)
formData.append(name, blob, fileName)
formData.set(name, value)
formData.set(name, blob, fileName)
Zde si všimněme dvou zvláštností:
set
metoda odstraní pole se stejným názvem,append
ne. To je jediný rozdíl mezi nimi.- Pro odeslání souboru je nutná syntaxe se 3 argumenty, posledním argumentem je název souboru, který se normálně přebírá z uživatelského souborového systému pro
<input type="file">
.
Další metody jsou:
formData.delete(name)
formData.get(name)
formData.has(name)
To je ono!