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
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
|
---
title: 在web应用程序中使用文件
slug: Web/API/File/Using_files_from_web_applications
tags:
- File
- File API
- ajax上传
- 文件
- 文件上传
translation_of: Web/API/File/Using_files_from_web_applications
---
<p>{{APIRef("File API")}}</p>
<p>通过使用在 HTML5 中加入到 DOM 的 File API,使在web内容中让用户选择本地文件然后读取这些文件的内容成为可能。用户可以通过HTML中的 {{HTMLElement("input/file", '<input type="file">')}} 元素或者是通过拖拽来选择本地文件。</p>
<p>如果你想通过扩展或者其它的chrome源码浏览器(browser chrome code)使用DOM File API,是可行的;然而,需要注意有一些附加特性。详细请见 <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>。</p>
<h2 id="访问被选择的文件">访问被选择的文件</h2>
<p>考虑这段 HTML:</p>
<pre class="brush: html notranslate"><input type="file" id="input"></pre>
<p>通过 File API,我们可以访问 {{DOMxRef("FileList")}},它包含了表示用户所选文件的 {{DOMxRef("File")}} 对象</p>
<p>如果用户只选择了一个文件,那么只需要考虑列表中的第一个文件。</p>
<p>使用传统的 DOM 选择器访问一个被选择的文件:</p>
<pre class="brush: js notranslate">const selectedFile = document.getElementById('input').files[0];
</pre>
<h3 id="通过_change_事件访问被选择的文件"><strong>通过 change 事件访问被选择的文件</strong></h3>
<p>可以(但不是强制的)通过 <code>change</code> 事件访问 {{DOMxRef("FileList")}}:</p>
<pre class="brush: html notranslate"><input type="file" id="input" onchange="handleFiles(this.files)"></pre>
<p>当用户选择一个文件时,<code>handleFiles()</code> 方法会用一个 {{DOMxRef("FileList")}} 对象作为参数被调用,{{DOMxRef("FileList")}} 对象包含表示用户选择的文件的 {{DOMxRef("File")}} 对象。</p>
<p>如果你想让用户选择多个文件,只需在 <code>input</code> 元素上使用 <code>multiple</code> 属性:</p>
<pre class="brush: html notranslate"><input type="file" id="input" multiple onchange="handleFiles(this.files)"></pre>
<p>在这个例子中,对于每个用户选择的文件,传递给 <code>handleFiles()</code>方法的文件列表都包含一个对应的 {{DOMxRef("File")}} 对象。</p>
<h3 id="动态添加change监听器"><strong>动态添加change监听器</strong></h3>
<p>你需要使用 {{DOMxRef("EventTarget.addEventListener()")}} 去添加 <code>change</code> 事件监听器,像这样:</p>
<pre class="brush: js notranslate">const inputElement = document.getElementById("input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
const fileList = this.files; /* now you can work with the file list */
}
</pre>
<p>注意在这个例子里,<code>handleFiles()</code> 方法本身是一个事件处理器,不像之前的例子中,它被事件处理器调用然后传递给它一个参数。</p>
<h2 id="获取被选择文件的信息">获取被选择文件的信息</h2>
<p>DOM 提供 {{ domxref("FileList") }} 对象列出了用户选择的所有文件,每一个文件被指定为一个 {{ domxref("File") }} 对象。你可以通过检查文件列表 {{ domxref("FileList") }} 的 <code>length</code> 属性来确定用户选择了多少个文件:</p>
<pre class="brush: js notranslate">const numFiles = files.length;
</pre>
<p>可以像数组一样简单地访问文件列表来检索各个 {{ domxref("File") }} 对象:</p>
<pre class="brush: js notranslate">for (let i = 0, numFiles = files.length; i < numFiles; i++) {
const file = files[i];
// ...
}</pre>
<p>这个循环遍历了文件列表里的所有文件。</p>
<p> {{ domxref("File") }} 对象提供了三个属性,包含了文件的有用信息。</p>
<dl>
<dt><code>name</code></dt>
<dd>文件名称,只读字符串。只包含文件名,不包含任何路径信息。</dd>
<dt><code>size</code></dt>
<dd>以字节数为单位的文件大小,只读的64位整数。</dd>
<dt><code>type</code></dt>
<dd>文件的 MIME 类型,只读字符串,当类型不能确定时为 <code>""</code>。</dd>
</dl>
<h3 id="示例:显示文件大小">示例:显示文件大小</h3>
<p>下面的例子展示了 <code>size</code> 属性的一种可能用法:</p>
<pre class="brush: html notranslate"><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File(s) size</title>
<script>
function updateSize() {
let nBytes = 0,
oFiles = document.getElementById("uploadInput").files,
nFiles = oFiles.length;
for (let nFileId = 0; nFileId < nFiles; nFileId++) {
nBytes += oFiles[nFileId].size;
}
let sOutput = nBytes + " bytes";
// optional code for multiples approximation
const aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
for (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">
<div>
<input id="uploadInput" type="file" name="myFiles" onchange="updateSize();" multiple>
selected files: <span id="fileNum">0</span>;
total size: <span id="fileSize">0</span>
</div>
<div><input type="submit" value="Send file"></div>
</form>
</body>
</html></pre>
<h2 id="通过_click_方法使用隐藏的_file_input_元素">通过 click() 方法使用隐藏的 file input 元素</h2>
<p>你可以隐藏公认难看的 file {{ HTMLElement("input") }} 元素并显示你自己的界面来打开文件选择器,然后显示哪个或哪些文件被用户选中了。你可以通过给 input 元素添加 <code>display:none</code> 的样式,再调用 {{HTMLElement("input") }} 元素的 {{domxref("element.click","click()") }} 方法来实现。</p>
<p>考虑这段HTML:</p>
<pre class="brush: html notranslate"><input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<button id="fileSelect">Select some files</button>
</pre>
<p>处理 <code>click</code> 事件的代码类似于这样:</p>
<pre class="brush: js notranslate">const fileSelect = document.getElementById("fileSelect"),
fileElem = document.getElementById("fileElem");
fileSelect.addEventListener("click", function (e) {
if (fileElem) {
fileElem.click();
}
}, false);
</pre>
<p>你可以给这个用来打开文件选择器的新按钮添加任何你想要的样式。</p>
<h2 id="使用_label_元素来触发一个隐藏的_file_input_元素">使用 label 元素来触发一个隐藏的 file input 元素</h2>
<p>允许在不使用 JavaScript(click() 方法)来打开文件选择器,可以使用 {{ HTMLElement("label") }} 元素。注意在这种情况下,input 元素不能使用 <code>display: none</code>(或 <code>visibility: hidden</code>)隐藏,否则 label 将无法通过键盘访问。使用 <a href="https://a11yproject.com/posts/how-to-hide-content/">visually-hidden technique</a> 作为替代。</p>
<p>考虑这段HTML:</p>
<pre class="brush: html notranslate"><input type="file" id="fileElem" multiple accept="image/*" class="visually-hidden">
<label for="fileElem">Select some files</label></pre>
<p>和这段CSS:</p>
<pre class="brush: css notranslate">.visually-hidden {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
}
/* Separate rule for compatibility, :focus-within is required on modern Firefox and Chrome */
input.visually-hidden:focus + label {
outline: thin dotted;
}
input.visually-hidden:focus-within + label {
outline: thin dotted;
}
</pre>
<p>这里不需要添加任何 JavaScript 代码来调用<code>fileElem.click()</code>,另外,这时你也可以给 label 元素添加你想要的样式。您需要在其 label 上提供隐藏 input 字段的焦点状态的视觉提示,比如上面用的轮廓,或者背景颜色或边框阴影。(截至编写时为止,Firefox 不显示 <code><input type="file"></code> 元素的视觉提示。)</p>
<h2 id="使用拖放来选择文件">使用拖放来选择文件</h2>
<p>你还可以让用户将文件拖拽到你的网页应用中。</p>
<p>第一步是创建一个drop区域。虽然你网页内容的哪部分接受拖放取决于你的应用设计,但是使一个元素接收drop事件是很容易的。</p>
<pre class="brush: js notranslate">let dropbox;
dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
</pre>
<p>在这个例子中,我们将ID为<code>dropbox</code>的元素变为了我们的drop区域。这是通过给元素添加{{event('dragenter')}}, {{event('dragover')}}, 和{{event('drop')}} 事件监听器实现的。</p>
<p>我们其实并不需要对<code>dragenter</code> and <code>dragover</code> 事件进行处理,所以这些函数都很简单。他们只需要包括禁止事件传播和阻止默认事件:</p>
<pre class="brush: js notranslate">function dragenter(e) {
e.stopPropagation();
e.preventDefault();
}
function dragover(e) {
e.stopPropagation();
e.preventDefault();
}
</pre>
<p>真正的奥妙在<code>drop()</code>这个函数中:</p>
<pre class="brush: js notranslate">function drop(e) {
e.stopPropagation();
e.preventDefault();
var dt = e.dataTransfer;
var files = dt.files;
handleFiles(files);
}
</pre>
<p>这里,我们从事件中获取到了<code>dataTransfer</code> 这个域,然后从中得到文件列表,再将它们传递给<code>handleFiles()</code>函数。在这之后,处理文件的方法和用<code>input</code>元素或者用拖拽就是一样的了。</p>
<h2 id="例子:显示用户选择的图片的缩略图">例子:显示用户选择的图片的缩略图</h2>
<p>比方说,你正在开发一个炫酷的下一代图片分享网站,并且想使用HTML5来展示用户在实际上传之前的图片的缩略图。你可以像我们之前讨论的那样创建自己的input元素或者drop区域,然后对他们使用一个回调函数,比如下面的<code>handleFiles()</code>。</p>
<pre class="brush: js notranslate">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); // 假设"preview"就是用来显示内容的div
var reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}
</pre>
<p>这里我们循环处理用户选择的文件,看每个文件的<code>type</code>属性是不是image(通过正则表达式来匹配MIME类型字符串模式"<code>image/*</code>")。 对每个文件而言,如果它是image,我们就创建一个新的<code>img</code>元素。可以使用css来创建一个漂亮的边框或阴影来显示图片的具体大小,在这儿就不具体做了。</p>
<p>为了在DOM树中更容易地找到他们,每个图片元素都被添加了一个名为<code>obj</code>的CSS类。我们还给每个图片添加了<code>file</code>属性使它具有 {{ domxref("File") }};这样做可以让我们拿到稍后需要实际上传的图片。我们在预览页中使用 {{ domxref("Node.appendChild()") }}来添加新的缩略图。</p>
<p>接下来,我们创建了{{ domxref("FileReader") }}来处理异步的图片加载并把他赋给<code>img</code>元素。在创建一个新的 <code>FileReader</code>对象后,我们新建了它的<code>onload</code> 函数,然后调用<code>readAsDataURL()</code>函数开始后台读取文件。当整个图片文件的内容都被全部加载完后,它们被转换成了一个被传递到<code>onload</code>回调函数的<code>data:</code>URL。我们再执行常规操作将<code>img</code>元素的<code>src</code>属性设置为刚刚加载完毕的URL,使得图像可以显示在用户屏幕上的缩略图中。</p>
<h2 id="使用对象_URL">使用对象 URL</h2>
<p>Gecko 2.0 {{ geckoRelease("2.0") }}引入了对DOM {{ domxref("window.URL.createObjectURL()") }} 和 {{ domxref("window.URL.revokeObjectURL()") }} 方法的支持。这使得你可以创建用于引用任何数据的简单URL字符串,也可以引用一个包括用户电脑上的本地文件的DOM {{ domxref("File") }}对象。</p>
<p>当你需要在HTML中通过URL来引用一个{{ domxref("File") }}对象时,你可以创建一个对象URL,就像这样:</p>
<pre class="brush: js notranslate">var objectURL = window.URL.createObjectURL(fileObj);
</pre>
<p>这个对象URL是一个标识{{ domxref("File") }}对象的字符串。每次你调用{{ domxref("window.URL.createObjectURL()") }},就会产生一个唯一的对象URL,即使是你对一个已创建了对象URL的文件再次创建一个对象URL。每个创建了的对象URL必须要释放。当文档关闭时,它们会自动被释放。如果你的网页要动态使用它们,你需要显式调用 {{ domxref("window.URL.revokeObjectURL()") }}来释放它们:</p>
<pre class="brush: js notranslate">window.URL.revokeObjectURL(objectURL);
</pre>
<h2 id="示例:使用对象URL来显示图片">示例:使用对象URL来显示图片</h2>
<p>这个例子使用对象URL来显示图片缩略图。另外,示例也会显示文件名和文件大小等其他文件信息。</p>
<p>显示接口的HTML类似于这样:</p>
<pre class="brush: html notranslate"><input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<a href="#" id="fileSelect">Select some files</a>
<div id="fileList">
<p>No files selected!</p>
</div>
</pre>
<p>这确定我们的文件 {{ HTMLElement("input") }} 元素显示为一个可以调用文件选择器的链接(我们隐藏了文件输入元素来阻止显示用户不友好的界面)。这个在 <a href="#通过_click_方法使用隐藏的_file_input_元素">通过 click() 方法使用隐藏的 file input 元素</a>已经说明了这种调用文件选择器的方法。</p>
<p><code>handleFiles()</code> 方法如下:</p>
<pre class="brush: js notranslate">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 {
fileList.innerHTML = "";
var list = document.createElement("ul");
fileList.appendChild(list);
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.createObjectURL(files[i]);
img.height = 60;
img.onload = function () {
window.URL.revokeObjectURL(this.src);
}
li.appendChild(img);
var info = document.createElement("span");
info.innerHTML = files[i].name + ": " + files[i].size + " bytes";
li.appendChild(info);
}
}
}</pre>
<p>首先,获取ID为 <code>fileList</code> 的 {{ HTMLElement("div") }} 。这个区块里我们会插入我们的文件列表,包括缩略图。</p>
<p>如果传入 <code>handleFiles()</code> 的 {{ domxref("FileList") }} 对象值为 <code>null</code> 时,我们只要简单将这块的内部HTML为显示“No files selected!”。否则,我们就需要像下面这样编写我们的文件列表:</p>
<ol>
<li><span>创建一个无序列表 ({{ HTMLElement("ul") }}) 元素。</span></li>
<li>通过调用列表的{{ domxref("Node.appendChild()") }}方法来将新的列表元素插入到 {{ HTMLElement("div") }}块。</li>
<li>遍历文件集合 {{ domxref("FileList") }}(即<code>files</code>)中的每个 {{ domxref("File") }}:
<ol>
<li>创建一个新的列表项({{ HTMLElement("li") }})元素并插入到列表中。</li>
<li>创建一个新的图片({{ HTMLElement("img") }})元素。</li>
<li>设置图片的源为一个新的指代文件的对象URL,使用{{ domxref("window.URL.createObjectURL()") }}来创建blob URL。</li>
<li>设置图片的高度为60像素。</li>
<li>设置图片的load事件处理器来释放对象URL,当图片加载完成之后对象URL就不再需要了。这个可以通过调用{{ domxref("window.URL.revokeObjectURL()") }}方法并且传递 <code>img.src</code>中的对象URL字符串来实现。</li>
<li>将新的列表项添加到列表中。</li>
</ol>
</li>
</ol>
<p>这是上面代码的一个在线示例:</p>
<p>{{EmbedLiveSample('示例:使用对象URL来显示图片', '100%', '300px')}}</p>
<h2 id="例子:上传一个用户选择的文件">例子:上传一个用户选择的文件</h2>
<p>另一件您可能想要做的事是让用户将选定的一个或多个文件(例如前一个示例中选择的图像)上传到服务器。这用异步可以很容易地完成。</p>
<h3 id="创建上传任务">创建上传任务</h3>
<p>继续前面示例中构建缩略图的代码,回想一下每个缩略图图像都在CSS类<code>obj</code>中,并且<code>file</code>属性中附加了相应的 {{ domxref("File") }} 。这允许我们使用 {{ domxref("Document.querySelectorAll()") }} 选择用户决定上传的所有图像,如下所示:</p>
<pre class="brush: js notranslate">function sendFiles() {
var imgs = document.querySelectorAll(".obj");
for (var i = 0; i < imgs.length; i++) {
new FileUpload(imgs[i], imgs[i].file);
}
}
</pre>
<p>第2行获取了文档中所有CSS类为<code>obj</code>的元素的 <span style="line-height: 1.5;">{{ domxref("NodeList") }}</span>,命名为<code>imgs</code>。在我们的例子中,这些是包含所有图像缩略图的列表。有了这个列表,遍历并为每一项创建一个新的<code>FileUpload</code>实例就很简单了。每个实例都可以处理相应文件的上传。</p>
<h3 id="Handling_the_upload_process_for_a_file处理文件的上传过程">Handling the upload process for a file处理文件的上传过程</h3>
<p><code>FileUpload</code>函数接受两个输入:一个image元素和一个包含图像数据的文件。</p>
<pre class="brush: js notranslate">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.send(evt.target.result);
};
reader.readAsBinaryString(file);
}
</pre>
<p>上面的<code>FileUpload()</code> 函数创建了一个“加载中”指示器,用于显示进度信息,然后创建了一个 {{ domxref("XMLHttpRequest") }} 来处理上传数据。</p>
<p>实际传输数据前,采取了几道准备步骤:</p>
<ol>
<li><code>XMLHttpRequest</code>的<code>progress</code>监听器被设为将加载指示器更新为新的百分比信息,这样随着上传进行,指示器会显示最新的信息。</li>
<li><code>XMLHttpRequest</code>的<code>load</code>事件监听器被设为将加载指示器的进度信息更新为100%,以保证进度显示确实达到了100%(以防在上传过程中出现粒度误差)。然后它移除了已经不再需要的加载指示器。这样上传一完成指示器就会消失。</li>
<li>上传图像文件的请求,是由调用<code>XMLHttpRequest</code>的<code>open()</code>函数发送POST请求完成的。</li>
<li>上传的MIME类型是通过调用<code>XMLHttpRequest</code>的<code>overrideMimeType()</code>函数来设置的。这个例子中,我们使用通用MIME类型。是否需要设置MIME类型取决于你的具体使用情况。</li>
<li><code>FileReader</code>对象用于将文件转换为二进制字符串。</li>
<li>最后,当内容被加载时,会调用<code>XMLHttpRequest</code>的<code>send()</code>函数来上传文件内容。</li>
</ol>
<div class="note"><strong>提示:</strong>上面例子中使用的非标准的<code>sendAsBinary</code>方法在Gecko 31 {{ geckoRelease(31) }} 中已废弃。请使用标准的<code>send(Blob data)</code>方法代替。</div>
<h3 id="异步处理文件上传">异步处理文件上传</h3>
<p>这个例子演示了如何异步上传文件,在服务器端使用了php、在客户端使用了JavaScript。</p>
<pre class="brush: js notranslate"><?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="application/javascript">
function sendFile(file) {
const uri = "/index.php";
const xhr = new XMLHttpRequest();
const fd = new FormData();
xhr.open("POST", uri, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText); // handle response.
}
};
fd.append('myFile', file);
// Initiate a multipart/form-data upload
xhr.send(fd);
}
window.onload = function() {
const dropzone = document.getElementById("dropzone");
dropzone.ondragover = dropzone.ondragenter = function(event) {
event.stopPropagation();
event.preventDefault();
}
dropzone.ondrop = function(event) {
event.stopPropagation();
event.preventDefault();
const filesArray = event.dataTransfer.files;
for (let 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="例子:用对象URL显示PDF">例子:用对象URL显示PDF</h2>
<p>对象URL可以用于image之外的其它东西!它可以用于显示嵌入的PDF文件或任何其它浏览器能显示的资源。</p>
<p>在Firefox中,要让PDF嵌入式地显示在iframe中(而不是作为下载的文件弹出),必须将<code>pdfjs.disabled</code>设为<code>false</code> {{non-standard_inline()}}.</p>
<pre class="brush: html notranslate"><iframe id="viewer">
</pre>
<p>这是<code>src</code>属性的改动:</p>
<pre class="brush: js notranslate">const obj_url = window.URL.createObjectURL(blob);
const iframe = document.getElementById('viewer');
iframe.setAttribute('src', obj_url);
window.URL.revokeObjectURL(obj_url);
</pre>
<h2 id="例子:将对象URL用于其它文件类型">例子:将对象URL用于其它文件类型</h2>
<p>你可以用同样方式操作其它格式的文件。这是预览上传的视频的方法:</p>
<pre class="brush: js notranslate">const video = document.getElementById('video');
const obj_url = window.URL.createObjectURL(blob);
video.src = obj_url;
video.play()
window.URL.revokeObjectURL(obj_url);</pre>
<h2 id="规范">规范</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">规范</th>
<th scope="col">状态</th>
<th scope="col">注解</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('HTML WHATWG', 'number-state.html#concept-input-type-file-selected', 'File upload state')}}</td>
<td>{{Spec2('HTML WHATWG')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('File API')}}</td>
<td>{{Spec2('File API')}}</td>
<td>Initial definition</td>
</tr>
</tbody>
</table>
<h2 id="相关链接">相关链接</h2>
<ul>
<li>{{DOMxRef("File")}}</li>
<li>{{DOMxRef("FileList")}}</li>
<li>{{DOMxRef("FileReader")}}</li>
<li>{{DOMxRef("URL")}}</li>
<li>{{DOMxRef("XMLHttpRequest")}}</li>
<li><a href="/en/DOM/XMLHttpRequest/Using_XMLHttpRequest" title="En/Using XMLHttpRequest">Using XMLHttpRequest</a></li>
</ul>
|