HTTP protokol není vhodný pro přenos binárních dat a prohlížeče to většinou řeší nejrůznějším šifrováním. Pokud ale chcete sami z JavaScriptu nahrát nějaký soubor na server a nechcete se příliš zabývat složitostmi, můžete použít trik se zakódováním do Base64.
Odeslání z JS
Nejprve je potřeba v JavaScriptu načíst soubor a převést ho na Base64:
f = new FileReader(); f.onload = function(e) { $.ajax({ url: 'upload.php', type: 'POST', contentType: 'application/octet-stream;charset=UTF-8', data: e.target.result .split(",", 2)[1], processData: false }); }; f.readAsDataURL($('input')[0].files[0]);
Je potřeba si dát pozor na několik věcí:
FileReader
nemusí být podporován ve starších prohlížečích.ContentType
musí uvádětUTF-8
, aby nedošlo k nechtěnému překódování dat (i když Base64 by měl být bezpečný).- Funkce
readAsDataUrl
vrací textovou hlavičku pro použití v HTML atributusrc
. Pro odeslání na server ji musíme odebrat (smazat vše před čárkou). - jQuery
$('input')
je potřeba nahradit za správný kód pro získáníinput
u typufile
. FileReader
je asynchronní, proto musíme nejprve uložit handler proonload
a pak teprve zavolat funkci pro načtení souboru.
Uložení na serveru
Následně v PHP (nebo jakémkoliv jiném jazyce) stačí přečíst POST data, dekódovat je z Base64 a uložit:
$base64 = file_get_contents('php://input'); $data = base64_decode($base64); file_put_contents(STORE . $filename, $data);
Práce s daty v PHP je jednoduchá, i když trochu zrádná pro nezkušeného programátora:
- Data ze vstupu čteme z
php://input
, který obsahuje data tak, jak vypadala před dekódováním do$_POST
. Proměnná$_POST
se totiž dá použít jen na správně formátovaná data a je nevhodná pro binární data, JSON, XML (SOAP), apod. - Funkce
file_*_contents()
usnadňují práci se soubory a odstraňují nutnost je otevírat a zase zavírat. - Načtená data jsou v Base64, takže je musíme před uložením na disk zase dekódovat.
- Konstanta
STORE
a proměnná$filename
by měly obsahovat cestu a jméno pro uložení souboru.
Na závěr jedna připomínka: Base64 změní data tak, že zabírají o třetinu více než původní soubor. Je tedy potřeba pamatovat na to, že pokud budete např. nahrávat 5MB fotku, musíte mít server nastavený tak, aby přijal alespoň 7MB v requestu.