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í:
FileReadernemusí být podporován ve starších prohlížečích.ContentTypemusí 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
readAsDataUrlvrací 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íinputu typufile. FileReaderje asynchronní, proto musíme nejprve uložit handler proonloada 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á$_POSTse 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
STOREa proměnná$filenameby 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.