1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
|
---
title: Zugriff auf Dateien von Webapplikationen
slug: Web/API/File/Using_files_from_web_applications
translation_of: Web/API/File/Using_files_from_web_applications
original_slug: Web/API/File/Zugriff_auf_Dateien_von_Webapplikationen
---
<p>Mithilfe der File API, welche mit HTML5 zum DOM hinzugefügt wurde, ist es nun für Webinhalte möglich den Benutzer lokale Dateien auswählen zu lassen und den Inhalt dieser Dateien auszulesen. Die Auswahl kann entweder durch das HTML Element {{ HTMLElement("input") }} oder durch Drag and Drop erfolgen.</p>
<p>Es ist auch möglich die DOM File API von Erweiterungen oder anderem Chrome Code zu benutzen. In diesem Fall müssen einige zusätzliche Dinge beachtet werden, die im Abschnitt <a href="/en/Extensions/Using_the_DOM_File_API_in_chrome_code" title="en/Extensions/Using the DOM File API in chrome code">Using the DOM File API in chrome code</a> näher erläutert werden.</p>
<h2 id="Auf_ausgewählte_Dateien_zugreifen">Auf ausgewählte Dateien zugreifen</h2>
<p>Gehen wir von folgendem HTML-Code aus:</p>
<pre class="brush: html"><input type="file" id="input"></pre>
<p>Die File API erlaubt den Zugriff auf eine {{ domxref("FileList") }} mit {{ domxref("File") }} Objekten, die die vom Benutzer ausgewählten Dateien repräsentieren.</p>
<p>Wenn der Benutzer nur eine Datei auswählt, dann muss nur die erste Datei in der Liste betrachtet werden.</p>
<p>Eine ausgewählte Datei erhält man über den üblichen DOM Selektor:</p>
<pre class="brush: js">var selectedFile = document.getElementById('input').files[0];</pre>
<p>Oder mit einem <a href="http://jquery.com/">jQuery</a> Selektor:</p>
<pre class="brush: js">var selectedFile = $('#input').get(0).files[0];
var selectedFile = $('#input')[0].files[0];</pre>
<div class="note">
<p>Tritt der Fehler "<code>files is undefined</code>" auf:<br>
Es wurde das falsche HTML element ausgewählt. Es ist zu beachten, dass ein jQuery Selektor eine Liste von zutreffenden DOM Elementen zurückliefert. Das richtige DOM Element muss ausgewählt werden, um "<code>files</code>" darauf anzuwenden.</p>
</div>
<h2 id="Zugriff_auf_ausgewählte_Dateien_über_den_Change_Event">Zugriff auf ausgewählte Dateien über den Change Event</h2>
<p>Es ist auch möglich (aber nicht unbedingt erforderlich), auf die {{ domxref("FileList") }} über das change event zuzugreifen:</p>
<pre class="brush: html"><input type="file" id="input" onchange="handleFiles(this.files)"></pre>
<p>Wenn der Benutzer eine Datei auswählt, wird die Funktion <code>handleFiles()</code> aufgerufen. Als Parameter wird die {{ domxref("FileList") }} übergeben. Sie enthält die {{ domxref("File") }} Objekte, die die vom Benutzer ausgewählten Dateien repräsentieren.</p>
<p>Soll der Benutzer mehrere Dateien auswählen können, dann kann einfach das Attribut <code>multiple</code> auf das <code>input</code> Element angewendet werden:</p>
<pre class="brush: html"><input type="file" id="input" multiple onchange="handleFiles(this.files)"></pre>
<p>In diesem Fall enthält die Dateiliste, die an die <code>handleFiles()</code> Funktion übergeben wird, ein {{ domxref("File") }} für jede Datei, die der Benutzer ausgewählt hat.</p>
<h3 id="Dynamisch_einen_Change_Listener_hinzufügen">Dynamisch einen Change Listener hinzufügen</h3>
<p>Wurde das <code>input</code> Feld mit einer JavaScript Bibliothek wie <a class="external" href="http://www.jquery.com/">jQuery</a> erzeugt, dann muss der event Listener mit {{ domxref("element.addEventListener()") }} hinzugefügt werden:</p>
<pre class="brush: js">var inputElement = document.getElementById("input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
var fileList = this.files; /* Jetzt kann die Dateiliste verarbeitet werden */
}</pre>
<p>In diesem Fall ist die <code>handleFiles()</code> Funktion selbst der Event Handler, anders als in den vorigen Beispielen, wo sie von einem Event Handler aufgerufen wurde.</p>
<h2 id="Informationen_über_die_ausgewählte(n)_Datei(en)">Informationen über die ausgewählte(n) Datei(en)</h2>
<p>Das {{ domxref("FileList") }} Objekt, das vom DOM geliefert wurde, enthält eine Liste aller Dateien, die vom Benutzer ausgewählt wurden. Jede der Dateien wird durch ein {{ domxref("File") }} Objekt repräsentiert. Die Anzahl der ausgewälten Dateien kann über das <code>length</code> Attribut der Liste ermittelt werden:</p>
<pre class="brush: js"><code>var numFiles = files.length;</code></pre>
<p>Die einzelnen {{ domxref("File") }} Objekte erhält man, indem das {{ domxref("FileList") }} Objekt einfach wie ein Array behandelt wird:</p>
<pre class="brush: js">for (var i = 0, numFiles = files.length; i < numFiles; i++) {
var file = files[i];
..
}
</pre>
<p>Diese Schleife iteriert über alle Dateien in der Liste.</p>
<p>Im {{ domxref("File") }} Objekt liefern drei Attribute hilfreiche Informationen über die Datei:</p>
<dl>
<dt><code>name</code></dt>
<dd>Der Dateiname als read-only String. Es ist nur der Dateiname enthalten, keine Pfadinformationen.</dd>
<dt><code>size</code></dt>
<dd>Die Dateigröße in Bytes als read-only 64-Bit Integer.</dd>
<dt><code>type</code></dt>
<dd>Der MIME type der Datei als read-only String oder <code>""</code>, wenn der Typ nicht ermittelt werden konnte.</dd>
</dl>
<h3 id="Beispiel_Dateigröße_anzeigen">Beispiel: Dateigröße anzeigen</h3>
<p>Das folgende Beispiel zeigt eine mögliche Verwendung des <code>size</code> Attributs:</p>
<pre class="brush: html"><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File(s) size</title>
<script>
function updateSize() {
var nBytes = 0,
oFiles = document.getElementById("uploadInput").files,
nFiles = oFiles.length;
for (var nFileId = 0; nFileId < nFiles; nFileId++) {
nBytes += oFiles[nFileId].size;
}
var sOutput = nBytes + " bytes";
// optional code for multiples approximation
for (var aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
sOutput = nApprox.toFixed(3) + " " + aMultiples[nMultiple] + " (" + nBytes + " bytes)";
}
// end of optional code
document.getElementById("fileNum").innerHTML = nFiles;
document.getElementById("fileSize").innerHTML = sOutput;
}
</script>
</head>
<body onload="updateSize();">
<form name="uploadForm">
<p><input id="uploadInput" type="file" name="myFiles" onchange="updateSize();" multiple> selected files: <span id="fileNum">0</span>; total size: <span id="fileSize">0</span></p>
<p><input type="submit" value="Send file"></p>
</form>
</body>
</html>
</pre>
<h2 id="Verstecktes_input_Element_mit_click()_Methode">Verstecktes input Element mit click() Methode</h2>
<p>Ab Gecko 2.0 {{ geckoRelease("2.0") }}, kann das zugegebenermaßen hässliche Datei-{{ HTMLElement("input") }} Element versteckt und durch eigene Oberflächenelemente zum Zugriff auf den Datei-Öffnen-Dialog ersetzt werden. Dazu wird das <code>input</code> Element mit dem CSS Stil <code>display:none</code> versehen und mit der Methode {{ domxref("element.click","click()") }} aufgerufen.</p>
<p>Gehen wir von folgendem HTML-Code aus:</p>
<pre class="brush: html"><code><input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<a href="#" id="fileSelect">Bitte Dateien auswählen</a>
</code>
</pre>
<p>Der Code, der auf den <code>click</code> Event reagiert, kann wie folgt aussehen:</p>
<pre class="brush: js">var fileSelect = document.getElementById("fileSelect"),
fileElem = document.getElementById("fileElem");
fileSelect.addEventListener("click", function (e) {
if (fileElem) {
fileElem.click();
}
e.preventDefault(); // prevent navigation to "#"
}, false);
</pre>
<p>Das neue Oberflächenelement zum Zugriff auf den Datei-Öffnen-Dialog kann nun beliebig gestaltet werden.</p>
<h2 id="label_Element_zum_Auslösen_eines_versteckten_input_Elements">label Element zum Auslösen eines versteckten input Elements</h2>
<p>Wird statt eines Links ({{ HTMLElement("a") }} Element) ein {{ HTMLElement("label") }} Element verwendet, dann kann das versteckte <code>input</code> Element auch ohne JavaScript ausgelöst werden. Dabei darf das input-Element aber weder mit <code>display: none</code> noch mit <code>visibility: hidden</code> versteckt werden, weil es in diesen Fällen nicht mit der Tastatur bedienbar wäre. Es darf nur <a href="https://a11yproject.com/posts/how-to-hide-content/">visuell versteckt</a> werden.</p>
<p>Gehen wir von folgendem HTML-Code aus:</p>
<pre class="brush: html"><input type="file" id="fileElem" multiple accept="image/*" class="visually-hidden">
<label for="fileElem">Bitte Dateien auswählen</label>
</pre>
<p>und folgendem CSS:</p>
<pre class="brush: css">.visually-hidden {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
}
input.visually-hidden:focus + label {
outline: thin dotted;
}
</pre>
<p>Bei einem Klick auf das <code>label</code> Element wird der Datei-Öffnen-Dialog angezeigt.</p>
<p>Das <code>label</code> Element kann per CSS beliebig gestaltet werden. Man muss aber das Label des versteckten Eingabefelds hervorheben, wenn dieses den Fokus hat, d.h. per Tab-Taste angewählt wurde – sei es durch outline wie im obigen Beispiel oder background-color oder box-shadow. (Gegenwärtig stellt Firefox das Label von fokussierten <code><input type="file"></code>-Elementen nicht hervorgehoben dar.)</p>
<h2 id="Dateien_per_Drag_and_Drop_auswählen">Dateien per Drag and Drop auswählen</h2>
<p>Es ist auch möglich, per Drag and Drop Dateien an die Webanwendung zu übergeben.</p>
<p>Zuerst muss eine Drop Zone eingerichtet werden. Welcher Teil der Oberfläche Drops entgegen nimmt, ist vom Design der Anwendung abhängig. Generell ist das Empfangen von Drop Events aber einfach:</p>
<pre class="brush: js">var dropbox;
dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
</pre>
<p>In diesem Beispiel wird das Element mit der ID <code>dropbox</code> als Drop Zone verwendet. Das wird durch Registrieren der Listener für {{event('dragenter')}}, {{event('dragover')}} und {{event('drop')}} Events erreicht.</p>
<p>dragenter und dragover benötigen wir in unserem Fall eigentlich nicht. Wir verhindern lediglich eine weitere Behandlung der Events durch Aufruf von <code>e.stopPropagation()</code> und <code>e.preventDefault()</code>:</p>
<pre class="brush: js">function dragenter(e) {
e.stopPropagation();
e.preventDefault();
}
function dragover(e) {
e.stopPropagation();
e.preventDefault();
}
</pre>
<p>Das Wesentliche geschieht in der Behandlung des <code>drop</code> Events:</p>
<pre class="brush: js">function drop(e) {
e.stopPropagation();
e.preventDefault();
var dt = e.dataTransfer;
var files = dt.files;
handleFiles(files);
}
</pre>
<p>Hier ermitteln wir das <code>dataTransfer</code> Feld aus dem Event, entnehmen ihm die Dateiliste und übergeben diese an <code>handleFiles()</code>. Von da an ist die Weiterverarbeitung die gleiche wie bei Verwendung des <code>input</code> Elements.</p>
<h2 id="Beispiel_Thumbnails_von_ausgewählten_Bildern_anzeigen">Beispiel: Thumbnails von ausgewählten Bildern anzeigen</h2>
<p>Gehen wir davon aus, dass auf einer Foto-Webseite mit HTML5 eine Thumbnail Vorschau von Bildern angezeigt werden soll, bevor sie hochgeladen werden. Das input Element oder die Drop Zone kann wie oben beschrieben eingerichtet werden. Diese rufen die folgende handleFiles() Funktion auf:</p>
<pre class="brush: js">function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /^image\//;
if (!imageType.test(file.type)) {
continue;
}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
preview.appendChild(img); // Gehen wird davon aus, dass "preview" das div-Element ist, in dem der Inhalt angezeigt wird.
var reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}
</pre>
<p>Mit der Schleife wird über die ausgewählten Dateien iteriert. Bei jeder Datei wird mit Hilfe des <code>type</code> Attributs (indem der Reguläre Ausdruck "^image\/" darauf angewendet wird) geprüft, ob es sich um eine Bild Datei handelt. Liegt eine Bild Datei vor, dann wird ein neues <code>img</code> Element erzeugt. Mit CSS können z.B. hübsche Ränder oder Schatten erzeugt und die Größe des Bildes festgelegt werden, das muss also nicht hier im Code erfolgen.</p>
<p>Jedem Bild wird die CSS Klasse <code>obj</code> zugewiesen, so dass es einfach ist, es im DOM Baum zu finden. Außerdem wird jedem Bild im <code>file</code> Attribut das {{ domxref("File") }} Objekt für das Bild zugewiesen; das benötigen wir später für den tatsächlichen Upload der Datei. Mit {{ domxref("Node.appendChild()") }} wird das neue Thumbnail dem <code>preview</code> Bereich unserer Anwendung hinzugefügt.</p>
<p>Dann erstellen wir einen {{ domxref("FileReader") }}, um das Bild asynchron zu laden und es dem <code>img</code> Element hinzuzufügen. Nach dem Erstellen des FileReader Objektes definieren wir die <code>onload</code> Funktion und rufen <code>readAsDataURL()</code> auf, um die Leseoperation im Hintergrund zu starten. Ist der komplette Inhalt der Bilddatei geladen, dann wird er in eine <code>data:</code> URL umgewandelt, die an den <code>onload</code> Callback übergeben wird. Unsere Implementation dieser Routine setzt das <code>src</code> Attribut des <code>img</code> Elements auf das geladene Bild, was dazu führt, dass das Bild im Thumbnail auf dem Bildschirm des Benutzers erscheint.</p>
<h2 id="Verwendung_von_Objekt_URLs">Verwendung von Objekt URLs</h2>
<p>Mit Gecko 2.0 {{ geckoRelease("2.0") }} wurde die Unterstützung für die DOM Methoden {{ domxref("window.URL.createObjectURL()") }} und {{ domxref("window.URL.revokeObjectURL()") }} eingeführt. Mit ihnen lassen sich einfache URL Strings erzeugen, die beliebige Daten referenzieren, auf die per DOM {{ domxref("File") }} Objekte zugegriffen werden kann; einschließlich lokale Dateien auf dem Computer des Anwenders.</p>
<p>Wenn man aus HTML mit einer URL auf ein {{ domxref("File") }} Objekt verweisen möchte, dann kann man dafür eine Objekt URL erzeugen:</p>
<pre class="brush: js"><code>var objectURL = window.URL.createObjectURL(fileObj);</code></pre>
<p>Die Objekt URL ist ein String, der das {{ domxref("File") }} Objekt identifiziert. Jedes Mal, wenn {{ domxref("window.URL.createObjectURL()") }} aufgerufen wird, wird eine eindeutige Objekt URL erzeugt, auch wenn vorher bereits eine Objekt URL für diese Datei erzeugt wurde. Jede von ihnen muss wieder freigegeben werden. Sie werden automatisch freigegeben, wenn das Dokument entladen wird. Wenn ihre Anwendung die Objekt URLs dynamisch verwendet, dann sollten Sie sie auch explizit durch Aufruf von {{ domxref("window.URL.revokeObjectURL()") }} freigeben:</p>
<pre class="brush: js"><code>window.URL.revokeObjectURL(objectURL);</code></pre>
<h2 id="Beispiel_Mit_Objekt_URLs_Bilder_anzeigen">Beispiel: Mit Objekt URLs Bilder anzeigen</h2>
<p>Dieses Beispiel verwendet Objekt URLs, um Thumbnails von Bildern anzuzeigen. Darüber hinaus werden weitere Dateiinformationen einschließlich Name und Größe angezeigt. <a href="/samples/domref/file-click-demo.html" title="https://developer.mozilla.org/samples/domref/file-click-demo.html">Live Ansicht des Beispiels</a>.</p>
<p>Das HTML für die Oberfläche sieht folgendermaßen aus:</p>
<pre class="brush: html"><input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<a href="#" id="fileSelect">Bitte Dateien auswählen</a>
<div id="fileList">
<p>Keine Dateien ausgewählt!</p>
</div>
</pre>
<p>Das erstellt ein Datei {{ HTMLElement("input") }} Element, zusammen mit einem Link, der den Datei-Öffnen-Dialog anzeigt (so kann das Datei <code>input</code> Element versteckt werden, da es nicht so attraktiv aussieht). Das wird oben im Abschnitt {{ anch("Verstecktes input Element mit click() Methode") }} näher beschrieben.</p>
<p>Die <code>handleFiles()</code> Methode sieht folgendermaßen aus:</p>
<pre class="brush: js">window.URL = window.URL || window.webkitURL;
var fileSelect = document.getElementById("fileSelect"),
fileElem = document.getElementById("fileElem"),
fileList = document.getElementById("fileList");
fileSelect.addEventListener("click", function (e) {
if (fileElem) {
fileElem.click();
}
e.preventDefault(); // prevent navigation to "#"
}, false);
function handleFiles(files) {
if (!files.length) {
fileList.innerHTML = "<p>No files selected!</p>";
} else {
var list = document.createElement("ul");
for (var i = 0; i < files.length; i++) {
var li = document.createElement("li");
list.appendChild(li);
var img = document.createElement("img");
img.src = window.URL.<strong>createObjectURL</strong>(files[i]);
img.height = 60;
img.onload = function() {
window.URL.<strong>revokeObjectURL</strong>(this.src);
}
li.appendChild(img);
var info = document.createElement("span");
info.innerHTML = files[i].name + ": " + files[i].size + " bytes";
li.appendChild(info);
}
}
}
</pre>
<p>Das {{ HTMLElement("div") }} Element mit der ID <code>fileList</code> wird ermittelt. Das ist der Block, in den wir später unsere Dateiliste einschließlich Thumbnails einfügen.</p>
<p>Ist das {{ domxref("FileList") }} Objekt, das an <code>handleFiles()</code> übergeben wird, <code>null</code>, dann wird einfach "No files selected!" ausgegeben. Ansonsten bauen wir unsere Dateiliste wie folgt:</p>
<ol>
<li>Ein neues ({{ HTMLElement("ul") }}) Element wird erzeugt.</li>
<li>Das neue Listenelement wird dem {{ HTMLElement("div") }} Block hinzugefügt durch Aufruf der {{ domxref("element.appendChild()") }} Methode.</li>
<li>Für jedes {{ domxref("File") }} in der {{ domxref("FileList") }}, die durch <code>files</code> repräsentiert wird:
<ol>
<li>Erzeuge ein neues Listenelement ({{ HTMLElement("li") }}) und füge es der Liste hinzu.</li>
<li>Erzeuge ein neues Bildelement ({{ HTMLElement("img") }}).</li>
<li>Setze das src Attribut des Bildes auf die neue Objekt URL, die die Datei repräsentiert, wobei die Objekt URL mit {{ domxref("window.URL.createObjectURL()") }} erzeugt wird.</li>
<li>Setze die Bildgröße auf 60 Pixel.</li>
<li>Richte den <code>onload</code> Event Handler ein, um die Objekt URL wieder freizugeben, da sie nach dem Laden des Bildes nicht mehr benötigt wird. Das wird durch Aufruf der Methode {{ domxref("window.URL.revokeObjectURL()") }} und Übergabe des Objekt URL Strings aus <code>img.src</code> gemacht.</li>
<li>Füge das neue Bildelement dem Listenelement hinzu.</li>
</ol>
</li>
</ol>
<h2 id="Example_Uploading_a_user-selected_file">Example: Uploading a user-selected file</h2>
<p>Another thing you might want to do is let the user upload the selected file or files (such as the images selected using the previous example) to a server. This can be done asynchronously very easily.</p>
<h3 id="Creating_the_upload_tasks">Creating the upload tasks</h3>
<p>Continuing with the code that built the thumbnails in the previous example, recall that every thumbnail image is in the CSS class <code>obj</code> with the corresponding {{ domxref("File") }} attached in a <code>file</code> attribute. This allows us to select all of the images the user has chosen for uploading using {{ domxref("Document.querySelectorAll()") }}, like this:</p>
<pre class="brush: js">function sendFiles() {
var imgs = document.querySelectorAll(".obj");
for (var i = 0; i < imgs.length; i++) {
new FileUpload(imgs[i], imgs[i].file);
}
}
</pre>
<p>Line 2 fetches a <span style="line-height: 1.5;">{{ domxref("NodeList") }}</span><span style="line-height: 1.5;">, called </span><code style="font-size: 14px;">imgs</code><span style="line-height: 1.5;">, of all the elements in the document with the CSS class </span><code style="font-size: 14px;">obj</code><span style="line-height: 1.5;">. In our case, these will be all of the image thumbnails. Once we have that list, it's trivial to go through it and create a new </span><code style="font-size: 14px;">FileUpload</code><span style="line-height: 1.5;"> instance for each. Each of these handles uploading the corresponding file.</span></p>
<h3 id="Handling_the_upload_process_for_a_file">Handling the upload process for a file</h3>
<p>The <code>FileUpload</code> function accepts two inputs: an image element and a file from which to read the image data.</p>
<pre class="brush: js">function FileUpload(img, file) {
var reader = new FileReader();
this.ctrl = createThrobber(img);
var xhr = new XMLHttpRequest();
this.xhr = xhr;
var self = this;
this.xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
self.ctrl.update(percentage);
}
}, false);
xhr.upload.addEventListener("load", function(e){
self.ctrl.update(100);
var canvas = self.ctrl.ctx.canvas;
canvas.parentNode.removeChild(canvas);
}, false);
xhr.open("POST", "http://demos.hacks.mozilla.org/paul/demos/resources/webservices/devnull.php");
xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
reader.onload = function(evt) {
xhr.sendAsBinary(evt.target.result);
};
reader.readAsBinaryString(file);
}
</pre>
<p>The <code>FileUpload()</code> function shown above creates a throbber, which is used to display progress information, and then creates an {{ domxref("XMLHttpRequest") }} to handle uploading the data.</p>
<p>Before actually transferring the data, several preparatory steps are taken:</p>
<ol>
<li>The <code>XMLHttpRequest</code>'s upload <code>progress</code> listener is set to update the throbber with new percentage information so that as the upload progresses the throbber will be updated based on the latest information.</li>
<li>The <code>XMLHttpRequest</code>'s upload <code>load</code> event handler is set to update the throbber progress information to 100% to ensure the progress indicator actually reaches 100% (in case of granularity quirks during the process). It then removes the throbber since it's no longer needed. This causes the throbber to disappear once the upload is complete.</li>
<li>The request to upload the image file is opened by calling <code>XMLHttpRequest</code>'s <code>open()</code> method to start generating a POST request.</li>
<li>The MIME type for the upload is set by calling the <code>XMLHttpRequest</code> function <code>overrideMimeType()</code>. In this case, we're using a generic MIME type; you may or may not need to set the MIME type at all depending on your use case.</li>
<li>The <code>FileReader</code> object is used to convert the file to a binary string.</li>
<li>Finally, when the content is loaded the <code>XMLHttpRequest</code> function <code>sendAsBinary()</code> is called to upload the file's content.</li>
</ol>
<div class="note"><strong>Note:</strong> The non-standard <code>sendAsBinary</code> method in the example above is considered deprecated as of Gecko 31 {{ geckoRelease(31) }} and will be removed soon. The standard <code>send(Blob data)</code> method can be used instead.</div>
<h3 id="Handling_the_upload_process_for_a_file_asynchronously">Handling the upload process for a file, asynchronously</h3>
<pre class="brush: js"><?php
if (isset($_FILES['myFile'])) {
// Example:
move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
exit;
}
?><!DOCTYPE html>
<html>
<head>
<title>dnd binary upload</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
function sendFile(file) {
var uri = "/index.php";
var xhr = new XMLHttpRequest();
var fd = new FormData();
xhr.open("POST", uri, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
// Handle response.
alert(xhr.responseText); // handle response.
}
};
fd.append('myFile', file);
// Initiate a multipart/form-data upload
xhr.send(fd);
}
window.onload = function() {
var dropzone = document.getElementById("dropzone");
dropzone.ondragover = dropzone.ondragenter = function(event) {
event.stopPropagation();
event.preventDefault();
}
dropzone.ondrop = function(event) {
event.stopPropagation();
event.preventDefault();
var filesArray = event.dataTransfer.files;
for (var i=0; i<filesArray.length; i++) {
sendFile(filesArray[i]);
}
}
}
</script>
</head>
<body>
<div>
<div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
</div>
</body>
</html>
</pre>
<h2 id="Example_Using_object_URLs_to_display_PDF">Example: Using object URLs to display PDF</h2>
<p>Object URLs can be used for other things than just images! They can be used to display embedded PDF files or any other resources that can be displayed by the browser.</p>
<p>In Firefox, to have the PDF appear embedded in the iframe (rather than proposed as a downloaded file), the preference <code>pdfjs.disabled</code> must be set to <code>false</code> {{non-standard_inline()}}.</p>
<pre class="brush: html"><iframe id="viewer">
</pre>
<p>And here is the change of the <code>src</code> attribute:</p>
<pre class="brush: js">var obj_url = window.URL.createObjectURL(blob);
var iframe = document.getElementById('viewer');
iframe.setAttribute('src', obj_url);
window.URL.revokeObjectURL(obj_url);</pre>
<h2 id="Example_Using_object_URLs_with_other_file_types">Example: Using object URLs with other file types</h2>
<p>You can manipulate files of other formats the same way. Here is how to preview uploaded video:</p>
<pre class="brush: js">var video = document.getElementById('video');
var obj_url = window.URL.createObjectURL(blob);
video.src = obj_url;
video.play()
window.URL.revokeObjectURL(obj_url);</pre>
<h2 id="Specification" name="Specification">Specifications</h2>
<ul>
<li><a class="external" href="http://www.w3.org/TR/progress-events/">File upload state</a> (HTML 5 working draft)</li>
<li><a href="http://www.w3.org/TR/FileAPI/">File API</a></li>
</ul>
<h2 id="See_also">See also</h2>
<ul>
<li>{{ domxref("File") }}</li>
<li>{{ domxref("FileList") }}</li>
<li>{{ domxref("FileReader") }}</li>
<li><a href="/en/DOM/XMLHttpRequest/Using_XMLHttpRequest" title="En/Using XMLHttpRequest">Using XMLHttpRequest</a></li>
<li><a href="/en/Extensions/Using_the_DOM_File_API_in_chrome_code" title="en/Extensions/Using the DOM File API in chrome code">Using the DOM File API in chrome code</a></li>
<li>{{ domxref("XMLHttpRequest") }}</li>
<li><a class="external" href="http://www.jquery.com/">jQuery</a> JavaScript library</li>
</ul>
|