Devel.cz Lupa Měšec Podnikatel Root Zdroják.cz DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Práce se soubory v prohlížeči, díl 1

Už několikrát jsme v článcích na Zdrojáku použili FileAPI, relativně novou součást webových technologií, která umožňuje číst, zpracovávat a ukládat soubory. V této minisérii se podíváme na nejrůznější nástroje a rozhraní, která využijete při zpracovávání souborů v prohlížečích, trochu podrobněji.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

0. Drobné odbočení na úvod k atributu download

Jistě jste ve své praxi řešili případ, kdy bylo na stránce potřeba odkázat na soubor s tím, že se po kliknutí uživateli neotevře, ale nabídne mu uložení jako download. U souborů s "dostatečně exotickým " MIME typem (míněno exotickým pro prohlížeč) to tak funguje vždy. Odkaz <a href="blabla.zip"> vyvolá rovnou stahovací dialog a nepokouší se nic otvírat.

Ale co obrázky, skripty nebo HTML stránky? Jak donutit prohlížeč, aby je neotvíral, ale nabízel ke stažení? Jedna z možností je nastavit na serveru patřičné hlavičky ( Content-Disposition atd.). Druhá možnost je o něco jednodušší: K odkazu se napíše poznámka „Klikněte pravým tlačítkem a vyberte Uložit odkaz jako…“

Tento problém řeší navrhovaný atribut download. Jeho hodnotou je jméno, pod nímž by měl být soubor uložen (samosebou si jej může uživatel v dialogu změnit).

<a href="logo.png" download="Logo Zdroják.cz">Stáhněte si naše logo</a>

Výsledkem je, že prohlížeč po kliknutí rovnou otevře ukládací dialog a nabídne uložení souboru. Šikovná věc, ale na jásání je brzy – atribut download je v tuto chvíli  implementován pouze v Chrome dev verzi (14.0.835.15+).

Zajímavé možnosti nabídne tento atribut ve spojení s blobURI či filesystem URI – a o nich bude řeč právě v souvislosti s FileAPIs.

1. Souborová API

Specifikace File API, File Writer API a File System API, resp. jejich návrhy, tvoří základ veškeré práce se soubory v prohlížečích. Pro všechny platí, že jsou v prohlížečích v různém stádiu implementace a zatím se nelze stoprocentně spolehnout, že v konkrétním prohlížeči budou fungovat, resp. že budou fungovat všechny funkce. Proto minimálně v následujících měsících využijete nejrůznější polyfills, tedy knihovny, které detekují existenci technologií, a pokud nejsou implementovány, nabídnou vlastní implementaci.

1. 1. File API

Toto API definuje základní konstrukce pro práci se soubory – Blob a File, metody pro čtení dat, synchronní čtení dat, vytváření URI pro soubory, chyby, výjimky a události, které se k souborům vážou.

1. 2. File Writer API

Druhé API přináší možnost vytvářet soubory v prohlížeči a zapisovat je lege artis na disk. Definuje BlobBuilder, základní nástroj pro vytváření souborů, a nástroje FileSaver a FileWriter, které ukládají obsah blobu na disk. Specifikace je stále ve fázi návrhu, takže je možné, že FileWriter se stane součástí Filesystem API.

1. 3. File System API

Toto API slouží pro práci se „sandboxed filesystem“, tedy s prostorem na disku, vyhrazeným pro „bezpečnou práci se soubory z prostředí prohlížeče“. Skripty tedy nebudou moci číst a zapisovat, kam se jim zamane, a přepsat tak např. systémové soubory; jejich prostor je omezen. Více o tomto API naleznete v článku První krůčky s FileSystem API.

2. Blob

Blob, neboli Binary Large OBject, je pojem, známý např. ze SQL či programovacích jazyků, kde vyjadřuje nestrukturovaný soubor binárních dat. Nestrukturovaný je zde myšleno ve vztahu k aplikaci, která s ní pracuje; například binární reprezentace obrázku ve formátu PNG zcela jistě vnitřní strukturu má, ovšem pokud je takový obrázek poslán na server a tam uložen do databáze, aniž by s ním aplikace jakkoli pracovala, měnila ho nebo z něj četla informace, může na něj nahlížet jako na shluk binárních dat, které pro ni nemají bezprostřední význam.

Podle File API je Blob objekt, který obsahuje právě ta binární data a navenek dává k dispozici readonly atributy size a type a nabízí metodu slice(start, length, type). Atribut size udává velikost souboru v bajtech a type obsahuje MIME typ dat. Metoda slice slouží k vytvoření nového blobu ze stávajícího pomocí zkopírování části, definované počátečním bajtem (start) a délkou (length). Třetí atribut je nepovinný a slouží k případné změně typu blobu.

3. File

Potomkem „třídy“ Blob je File – k výše popsaným atributům přidává další R/O atributy name a lastModifiedDate. Name obsahuje jméno souboru (jen jméno bez cesty) a lastModifiedDate informaci o poslední změně souboru.

4. FileReader

Pokud chceme pracovat s daty v blobu či souboru přímo v JavaScriptu, musíme je nejprve přečíst – tedy převést do tvaru, který lze v JS zpracovávat. K tomu slouží právě metody objektu FileReader. FileReader nabízí základní metody readAsBinaryString, readAsDataURL, readAsTextreadAsArrayBuffer.

var reader = new FileReader();
reader.onload = function(event) { ... };
reader.readAsBinaryString(blob);

V obsluze události onload můžeme zpracovat načtený obsah ve tvaru binárního řetězce (readAsBinaryS­tring), datového URL (readAsDataURL), textu (readAsText) či ArrayBuffer. Obsah bude dostupný přes vlastnost  result:

reader.onload = function(event) { ...
   var data = event.target.result;
...}

Všechny zmíněné metody mají jako parametr blob. U metody readAsText() lze zadat i druhý nepovinný parametr encoding a určit případné překódování znaků.

FileReader nabízí i atributy readyState a error. První obsahuje stav readeru (0 = nic se nedělá, 1 = probíhá čtení, 2 = čtení dokončeno), druhý obsahuje objekt FileError, který udává chybu, ke které při čtení došlo.

Kromě zmíněné události load nabízí FileReader i události loadstart, loadend (voláno při začátku čtení, resp. při skončení), error (při výskytu chyby), abort (při skončení čtení) a progress (voláno během čtení). U události progress můžeme z atributů loaded a total zjistit, kolik dat bylo zpracováno a kolik zbývá.

reader.onprogress = updateProgress;
...
function updateProgress(event) {
  if (event.lengthComputable) {
    var loaded = (event.loaded / event.total);
    if (loaded < 1) {
       bar.style.width = (loaded * 200) + "px";
    }
  }
}

Pěkné… ale kde ten blob vezmu?

Velmi správná otázka. Hovoříme tu o zpracování souborů, ale zatím nepadlo ani slovo o tom, jak se z klasického souboru, co leží někde na disku, stane blob.

Máme několik způsobů (a teď pomineme File System API). Můžeme si blob ručně vytvořit pomocí BlobBuilderu (o kterém bude ještě řeč), nebo můžeme nechat uživatele, aby soubor vybral a v prohlížeči otevřel.

Můžeme využít buď novější postup s drag-and-drop (viz článek Práce se soubory v HTML5) nebo klasický způsob s <input type=file>. Samozřejmě lze použít i obě metody najednou (což může přispět ke zlepšení použitelnosti) – samotná obsluha načítání souborů zůstává stejná, mění se pouze sledované události. U elementu input file můžeme obsloužit událost  change:

<input type=file id=upload>
var upload = document.getElementById('upload');
upload.onchange = function (event) {
   var file = upload.files[0];
   // ve file máme kýžený "blob" pro další zpracování
}

Pole files u elementu input file obsahuje jednotlivé soubory jako položky typu File. Pokud je použit v elementu atribut multiple, může být položek víc, jinak bude obsahovat položku jedinou.

Blob lze vytvořit i interně, a to jak „na zelené louce“ (pomocí Builderu), tak z HTML elementů, které podporují metodu toBlob() (např. canvas). Obojí bude námětem dalších dílů.

Příklad: Jak načíst soubor?

Ukažme si použití těchto informací v jednoduchém příkladu: necháme uživatele vybrat soubor s obrázkem, a ten zobrazíme. Autorem příkladu je Remy Sharp.

V HTML je několik prvků pro uživatelské rozhraní:

  <p id="status">File API &amp; FileReader API not supported</p>
  <p><input type=file></p>
  <p>Select an image from your machine to read the contents of the file without using a server</p>
  <div id="holder"></div>

Odstavec #status udává stav aplikace, tedy zda je čtení souborů podporováno a zda je možné je použít. Dále je v kódu vlastní input pro výběr souboru, popis a div#holder, v němž se bude obrázek zobrazovat.

Zbytek je obsloužen skriptem. Je testována dostupnost API:

if (typeof window.FileReader === 'undefined') {
  state.className = 'fail';
} else {
  state.className = 'success';
  state.innerHTML = 'File API & FileReader available';
}

a následně je nadefinována obsluha:

var upload = document.getElementsByTagName('input')[0],
    holder = document.getElementById('holder'),
    state = document.getElementById('status');

upload.onchange = function (e) {
  e.preventDefault();

  var file = upload.files[0],
      reader = new FileReader();
  reader.onload = function (event) {
    var img = new Image();
    img.src = event.target.result;
    // note: no onload required since we've got the dataurl...I think! :)
    if (img.width > 560) { // holder width
      img.width = 560;
    }
    holder.innerHTML = '';
    holder.appendChild(img);
  };
  reader.readAsDataURL(file);

  return false;
};

V obsluze události change je nejprve zabráněno vykonání předdefinovaných akcí. Výše uvedeným způsobem je získán z vybraného souboru blob a vytvořen nový FileReader, kterému je blob předán jako parametr metody readAsDataURL(). Obsluha události onload vytvoří HTML element <img>, nastaví mu atribut src na hodnotu, která je vrácena Readerem jako result  – tedy datové URL, a uloží jej do připraveného kontejneru  holder.

V příkladu nejsou ošetřeny chybové stavy ani není obrázek nějak upravován. Jde čistě jen o demonstraci čtení souborů. (Můžete se podívat na tentýž příklad s použitím drag-and-drop)

A dál…?

V dalším pokračování si probereme vytváření souborů v prohlížeči a jejich zápis. Podíváme se, jak uložit obrázek z canvasu a jak vytvořit dočasnou kódovou URL pro objekt.

Martin Malý

Martin Maly

Začal programovat v roce 1984 s progra­movatelnou kalkulačkou. Pokračoval k BASICu, assembleru Z80, Forthu, Pascalu, Céčku, dalším assemblerům, před časem v PHP a teď je rád, že neprogramuje…

Školení: Návrh a používání MySQL databáze

 

Naučte se používat jednu z nejrozšířenějších databází. Dozvíte se vše potřebné od návrhu až po samotné využití MySQL v projektech.

Školení pro všechny, kteří se chtějí naučit efektivně pracovat s MySQL nebo se v práci s touto databází zlepšit.

Přihláška a podrobné informace

Přehled názorů

Poslední ukázka
Bronislav Klučka 15. 8. 2011 03:26
Nový
├ 
Re: Poslední ukázka
Martin Malý 15. 8. 2011 08:06
Nový
└ 
Re: Poslední ukázka
Roman Jakubec 15. 8. 2011 10:21
Nový
 
└ 
Re: Poslední ukázka
Bronislav Klučka 15. 8. 2011 14:08
Nový
input nebo drag'n'drop
besh 15. 8. 2011 09:48
Nový
└ 
Re: input nebo drag'n'drop
Martin Malý 15. 8. 2011 10:40
Nový
OT ad 0: (vylev zhrzeneho genia)
starenka 17. 8. 2011 08:45
Nový
├ 
Re: OT ad 0: (vylev zhrzeneho genia)
Martin Malý 17. 8. 2011 08:47
Nový
│
└ 
Re: OT ad 0: (vylev zhrzeneho genia)
Jirka Kosek 17. 8. 2011 12:29
Nový
├ 
HTTP ne HTML
Franta Kučera 17. 8. 2011 10:02
Nový
└ 
Re: OT ad 0: (vylev zhrzeneho genia)
Franta Kučera 17. 8. 2011 10:28
Nový
 
├ 
Re: OT ad 0: (vylev zhrzeneho genia)
Martin Malý 17. 8. 2011 11:55
Nový
 
│
└ 
Re: OT ad 0: (vylev zhrzeneho genia)
Franta Kučera 18. 8. 2011 12:07
Nový
 
│
 
└ 
Re: OT ad 0: (vylev zhrzeneho genia)
Jirka Kosek 18. 8. 2011 14:24
Nový
 
└ 
Re: OT ad 0: (vylev zhrzeneho genia)
Jirka Kosek 17. 8. 2011 12:34
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem