视频讲解



第5章HTML5中的文件
本章学习目标
 掌握选择上传文件的使用方法。
 了解并理解文件读取与拖放的过程。
 熟悉文件读取时的错误与异常的处理方法。
5.1选择文件

与HTML4前版本相同,在HTML5中,可以创建一个file类型的input元素实现文件的上传功能,只是在HTML5中,该类型的input元素新添加了一个multiple属性,如果将属性的值设置为true,那么可以在一个元素中实现多个文件的上传。另外,通过访问Blob对象,可以获取上传文件的类型、大小属性。下面分别进行详细的介绍。
5.1.1选择单个文件
在HTML5中,创建一个file类型的input元素上传文件时,该元素在页面中的展示方式发生了变化,不再有文本框,而是一个选择文件的按钮,按钮的右边显示选择上传文件的名称,初始化页面时,没有上传文件,因此,显示“未选择文件”字样。
下面通过一个简单的实例介绍如何选择单个文件并上传的过程。
实例51选择单个文件上传
1. 功能描述

在页面中,创建一个file类型的input元素,单击该元素的“选择文件”按钮,选择一个图片文件,单击“打开”按钮或双击该文件后,在页面中“选择文件”按钮的右侧将显示所选择图片文件的名称,表明已将该文件选中,等待上传。
2. 实现代码
在WebStorm中新建一个HTML页面51.html,加入代码如代码清单51所示。

代码清单51选择单个文件上传




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>选择单个文件上传</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

</head>

<body>

<form id="frmTmp">

 <fieldset>

<legend>上传单个文件: </legend>

 <input type="file" name="fleUpload" id="fleUpload"/>

</fieldset>

</form>

</body>

</html>








3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图51所示。


图51使用file类型的input元素实现单个文件选择时的效果


4. 源码分析
在本实例中,单击“选择文件”按钮,选中上传文件后,没有编写任何的JavaScript代码,在页面中显示所选择的文件名称
。当然,如果该名称太长,在页面显示时,将采取两端显示,中间省略号的形式展示,例如,图片名称为“jQuery 权威指南_2010年作品”,那么页面显示为“jQuery 权威
...10年作品.jpg”。
5.1.2选择多个文件
在HTML5中,除了使用file类型的input元素选择单个文件外,还可以通过添加元素的multiple属性,并将该属性值设为true,
实现选择多个文件的功能。

一个文件对应一个file对象,该对象中有两个重要的属性,一个是name,表示不包含路径的文件名称; 另外一个属性是lastModifiedDate,表示文件最后修改的时间。当使用file类型的input元素选择多个文件时,该元素中就含有多个file对象,从而形成了FileList对象,即FileList对象就是指file对象的列表。
下面通过一个简单的实例介绍如何选择多个文件上传的过程。
实例52选择多个文件上传
1. 功能描述

在页面中,创建一个file类型的input元素,添加multiple属性,并将该属性的值设置为true,当单击“选择文件”
按钮时,同时选择三个文件,单击“打开”按钮后,页面中在“选择文件”按钮的后面将显示“3个文件”的字样,移动鼠标指针到文字上时,显示这3个文件的详细名称与类型。
2. 实现代码
在WebStorm中新建一个HTML页面52.html,加入代码如代码清单52所示。

代码清单52选择多个文件上传




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>选择多个文件上传</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

</head>

<body>

<form id="frmTmp">

 <fieldset>

<legend>上传多个文件: </legend>

<input type="file" name="fleUpload"

id="fleUpload" multiple="true"/>

</fieldset>

</form>

</body>

</html>




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图52所示。


图52使用file类型的input元素实现多个文件选择时的效果


4. 源码分析
在本实例中,由于file类型的input元素中添加了multiple属性,因此,可以通过该元素选择多个文件进行上传,选择成功后,“选择文件”按钮右侧不再显示文件的名称,而是显示成功选择上传文件的总量,当将鼠标指针移至总量上时,显示全部上传文件的详细列表。
当多个上传文件被选中时,在上传文件元素中,将会产生一个FileList对象,用来装载各文件的基本信息,如文件名称、类型、大小等。在上传文件总量的文字上移动鼠标指针时,将调用该对象的列表信息,展示在页面中。
5.1.3使用Blob接口获取文件的类型与大小

Blob表示二进制数据块。Blob接口中提供了一个slice()方法,通过该方法可以访问指定长度与类型的字节内部数据块。此外,该接口还提供了两个属性,一个为size,表示返回数据块的大小; 另外一个为type,表示返回数据块的MIME类型。如果不能确定数据块的类型,则返回一个空字符串。在实例51与实例52中的file对象,实质上是Blob接口的一个实体,完全继承了该接口中的方法与属性。
下面通过一个实例介绍file对象如何继承Blob接口获取文件类型与大小的过程。
实例53获取上传文件的类型与大小
1. 功能描述

在页面的表单中,创建一个file类型的input元素,并将该元素的multiple属性设置为true,表示允许选择多个上传文件。单击“选择文件”按钮,选取多个需要上传的文件后,在页面中,将以列表的方式展示所选文件的名称、类型、大小信息。
2. 实现代码
在WebStorm中新建一个HTML页面53.html,加入代码如代码清单531所示。

代码清单531获取上传文件的类型与大小




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>获取上传文件的类型与大小</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

<script type="text/javascript" language="jscript"

src="Js/js3.js">

</script>

</head>







<body>

<form id="frmTmp">

 <fieldset>

<legend>上传多个文件: </legend>

<input type="file" name="fleUpload" id="fleUpload" 

onChange="fileUpload_GetFileList(this.files);" 

multiple="true"/>

<ul id="ulUpload"></ul>

</fieldset>

</form>

</body>

</html>




在实例53中,页面导入一个JavaScript文件js3.js,在该文件中,调用fileUpload_GetFileList() 方法,以列表的形式展示上传文件的数据信息,其实现的代码如代码清单532所示。

代码清单532实例53中的JavaScript文件js3.js的源码




// JavaScript Document

function $$(id) {

return document.getElementById(id);

}

//选择上传文件时调用的函数

function fileUpload_GetFileList(f) {

var strLi = "<li class='li'>";

strLi = strLi + "<span>文件名称</span>";

strLi = strLi + "<span>文件类型</span>";

strLi = strLi + "<span>文件大小</span>";

strLi = strLi + "</li>";

for (var intI = 0; intI < f.length; intI++) {

var tmpFile = f[intI];

strLi = strLi + "<li>";

strLi = strLi + "<span>" + tmpFile.name + "</span>";

strLi = strLi + "<span>" + tmpFile.type + "</span>";

strLi = strLi + "<span>" + tmpFile.size + " KB</span>";

strLi = strLi + "</li>";

}


$$("ulUpload").innerHTML = strLi;

}




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图53所示。


图53使用file类型的input元素获取上传文件类型与大小时的效果



4. 源码分析
在页面加粗代码中,file类型的input元素,选择上传文件时,将触发onChange事件,在该事件中,调用自定义的函数fileUpload_GetFileList(this.files),其中,实参this.files表示所选择的上传文件集合,即FileList对象; 在函数fileUpload_GetFileList()中,遍历传回的FileList文件集合,获取单个的file对象,该对象通过继承Blob接口的属性,返回文件的名称、类型、大小信息,并将这些信息以叠加的方式保存在变量strLi中; 最后,将变量的内容赋值给id为ulUpload的列表元素,通过列表元素,将上传文件的信息展示在页面中。详细实现过程见代码中加粗部分。
5.1.4通过类型过滤选择的文件
在实例53中,通过file对象可以获取每个上传文件的名称、类型、大小,根据这个特征,可以过滤上传文件的类型。具体流程是: 当选择上传文件后,遍历每一个file对象,获取该对象的类型,并将该类型与设置的过滤类型进行匹配,如果不符合,则提示上传文件类型出错或拒绝上传,从而实现在选择上传文件时,就通过类型过滤了需要上传的文件。
下面通过一个实例介绍file对象通过类型过滤选择文件的过程。
实例54通过类型过滤上传文件
1. 功能描述

在页面表单中,创建一个file类型的input元素,并设置multiple属性为true,用于上传多个文件; 当单击“选择文件”按钮,并选取了需要上传的文件后,如果选取的文件中存在不符合“图片”类型的文件,将在页面中显示总数量与文件名称。
2. 实现代码
在WebStorm中新建一个HTML页面54.html,加入代码如代码清单541所示。

代码清单541通过类型过滤上传文件




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>通过类型过滤上传文件</title>

<link href="css/css5.css" rel="stylesheet" type="text/css">

<script type="text/javascript" language="jscript"







src="Js/js4.js">

</script>

</head>

<body>

<form id="frmTmp">

 <fieldset>

<legend>上传过滤类型后的文件: </legend>

<input type="file" name="fleUpload" id="fleUpload"

onChange="fileUpload_CheckType(this.files);"

multiple="true" />

<p id="pTip"/>

</fieldset>

</form>

</body>

</html>




在实例54中,页面导入一个JavaScript文件js4.js,在该文件中,调用fileUpload_CheckType() 方法,并且按照设置的类型格式过滤需要上传的文件,其实现的代码如代码清单542所示。

代码清单542实例54中的JavaScript文件js4.js的源码





// JavaScript Document

function $$(id) {

return document.getElementById(id);

}

//选择上传文件时调用的函数

function fileUpload_CheckType(f) {

var strP = "",

strN = "",

intJ = 0;

var strFileType = /image.*/;

for (var intI = 0; intI < f.length; intI++) {

var tmpFile = f[intI];

if (!tmpFile.type.match(strFileType)) {

intJ = intJ + 1;

strN = strN + tmpFile.name + "<br>";

}

}

strP = "检测到(" + intJ + ")个非图片格式文件。";

if (intJ > 0) {

strP = strP + "文件名如下: <p>" + strN + "</p>";

}

$$("pTip").innerHTML = strP;

}




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图54所示。


图54使用file类型的input元素过滤上传文件类型时的效果


4. 源码分析
在实例53中,我们知道,如果上传文件是图片类型,则file对象返回的类型均以image/开头,后面添加“*”表示所有的图片类型或添加gif表示某种类型图片; 因此,如果是一个图片文件,那么,该文件返回的类型必定以image/字样开头。
根据这一特点,在本实例中,当遍历传回的文件集合时,通过match()方法检测每个文件返回的类型中是否含有image/*字样,如果没有,则说明是非图片类型文件,分别将总量与文件名称以叠加的形式保存在变量中; 然后,将变量的内容赋值给id为pTip的元素,最后,通过该元素显示全部过滤文件的总量与名称表。详细实现过程见代码中加粗部分。
5.1.5通过accept属性过滤选择文件的类型

在选择上传文件后,根据文件返回的类型过滤所选择的文件,是一种不错的方法,但需要编写不少的代码,除此方法之外,在HTML5中,还可以设置file类型input元素的accept属性为文件的过滤类型; 设置完accept属性值后,在打开窗口选择文件时,默认的文件类型就是所设置的过滤类型。
下面通过一个实例简单介绍file类型input元素通过属性过滤选择文件类型的过程。
实例55通过accept属性过滤上传文件的类型
1. 功能描述

在页面表单中,创建一个file类型的input元素,并在元素中添加一个accept属性,属性值设置为image/gif,当用户单击“选择文件”按钮时,在打开的文件选择窗口中,文件类型为accept属性所设置的值。
2. 实现代码
在WebStorm中新建一个HTML页面55.html,加入代码如代码清单55所示。

代码清单55通过类型过滤上传文件




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>通过accept属性过滤某类型上传文件</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

</head>

<body>

<form id="frmTmp">

<fieldset>

<legend>选择某类型上传文件: </legend>

<input type="file" name="fleUpload" 

id="fleUpload" accept="image/gif" />

</fieldset>

</form>

</body>

</html>




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图55所示。


图55使用file类型的input元素通过设置accept属性过滤上传文件类型时的效果


4. 源码分析

在本实例中,由于对文件元素添加了accept属性,并设置image/gif类型作为该属性的值,因此,当单击“选择文件”按钮打开窗口时,其默认的选择文件类型就是所设置accept的属性值。详细实现过程见代码中加粗部分。
通过简单设置元素的一个属性,就可以在文件选择前过滤所选文件的类型,这种方法代码简单,操作方便。但是在目前的浏览器中,该方法不是很有效,原因在于,即便通过属性设置了文件选择的类型,但不是该类型的文件同样也可以被选中,也能被元素所接受。因此,使用这种过滤上传文件类型方法时,还需要谨慎。
5.2读取与拖放文件
使用Blob接口可以获取上传文件的相关信息,如文件名称、大小、类型,但如果想要读取或浏览文件,则需要通过FileReader接口,该接口不仅可以读取图片文件,还可以读取文本或二进制文件。同时,根据该接口提供的事件与方法,可以动态侦察文件读取时的详细状态,接下来详细介绍FileReader接口的使用方法。
5.2.1FileReader 接口
FileReader接口提供了一个异步的API,通过这个API可以从浏览器主线程中异步访问文件系统中的数据,基于此原因,FileReader 接口可以读取文件中的数据,并将读取的数据放入内存中。
当访问不同文件时,必须重新调用FileReader 接口的构造函数,因为每调用一次,FileReader 接口都将返回一个新的FileReader对象,只有这样,才能实现访问不同文件的数据。

FileReader接口提供了一整套完整的事件处理机制,用于侦察FileReader对象读取或返回数据时的各种进程状态。
FileReader接口的常用事件如表51所示。


表51FileReader接口的常用事件



事 件 名 称说明


onloadstart当读取数据开始时,触发该事件
onprogress当正在读取数据时,触发该事件
onabort当读取数据终止时,触发该事件
onerror 当读取数据失败时,触发该事件
onload当读取数据成功时,触发该事件
onloadend当请求操作成功时,无论操作是否成功,都触发该事件

在FileReader 接口中,除提供了常用事件外,还拥有许多常用的方法,用于读取文件或响应事件,如onabort事件触发时,就要调用abort()方法。FileReader接口的常用方法如表52所示。


表52FileReader接口的常用方法



方 法 名 称参数功 能 说 明


readAsBinaryString()file以二进制的方式读取文件内容
readAsArrayBuffer()file以数组缓冲的方式读取文件内容
readAsText()file,encoding以文本编码的方式读取文件内容
readAsDataURL()file以数据URL的方式读取文件内容
Abort()无读取数据终止时,将自动触发该方法

针对FileReader接口中的方法,使用说明如下。
 调用readAsBinaryString()方法时,将file对象返回的数据块,作为一个二进制字符串的形式,分块读入内存中。
 调用readAsArrayBuffer()方法时,将file对象返回的数据字节数,以数组缓冲的方式读入内存中。
 调用readAsText()方法时,其中encoding参数表示文本文件编码的方式,默认值为UTF8,即以UTF8编码格式将获取的数据块按文本方式读入内存中。
 调用readAsDataURL()方法时,将file对象返回的数据块,以一串数据URL字符的形式展示在页面中,这种方法一般读取数据块较小的文件。
5.2.2使用FileReader()方法预览图片文件

在前面的实例中,通过Blob接口可以访问文件数据块,获取文件相关信息。但如果想要读取文件,还需要通过FileReader 接口中的方法,将数据读入内存或页面中。例如,尺寸较小的图片文件,可以通过FileReader 接口中的readAsDataURL()方法,获取API异步读取的文件数据,另存为数据URL,将该URL绑定img元素的src属性值,就可以实现图片文件预览的效果。
下面通过一个实例介绍使用readAsDataURL()方法预览图片的过程。
实例56使用readAsDataURL()方法预览图片
1. 功能描述

在页面表单中,添加一个file类型的input元素,用于选择上传文件,并设置属性multiple的值为true,表示允许上传多个文件,
单击“选择文件”按钮后,如果选择的是图片文件,将在页面中显示,实现图片文件上传的预览功能。
2. 实现代码
在WebStorm中新建一个HTML页面56.html,加入代码如代码清单561所示。

代码清单561使用readAsDataURL()方法预览图片




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>使用readAsDataURL()方法预览图片</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

<script type="text/javascript" language="jscript"

src="Js/js6.js">

</script>

</head>

<body>

<form id="frmTmp">

<fieldset>

<legend>预览图片文件: </legend>

<input type="file" name="fleUpload" id="fleUpload" 

onChange="fileUpload_PrevImageFile(this.files);" 

multiple="true"/>

<ul id="ulUpload"></ul>







 </fieldset>

</form>

</body>

</html>




在实例56中,页面导入一个JavaScript文件js6.js,在该文件中,调用fileUpload_PrevImageFile()方法,该方法访问fileReader接口,将文件以数据URL的方式返回页面,其实现的代码如代码清单562所示。

代码清单562实例56中的JavaScript文件js6.js的源码




// JavaScript Document

function $$(id) {

return document.getElementById(id);

}

//选择上传文件时调用的函数

function fileUpload_PrevImageFile(f) {

//检测浏览器是否支持FileReader对象

if (typeof FileReader == 'undefined') {

alert("检测到您的浏览器不支持FileReader对象!");

}

var strHTML = "";

for (var intI = 0; intI < f.length; intI++) {

var tmpFile = f[intI];

var reader = new FileReader();

reader.readAsDataURL(tmpFile);

reader.onload = function(e) {

strHTML = strHTML + "<span>";

strHTML = strHTML + "<img src='" + e.target.result

+ "' alt=''/>";

strHTML = strHTML + "</span>";

$$("ulUpload").innerHTML = "<li>" + strHTML + "</li>";

}

}

}




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图56所示。


图56使用readAsDataURL()方法预览图片时的效果


4. 源码分析
在本实例中,图片预览的过程实质上是图片文件被读取后展示在页面中的过程,为了实现这一过程,需要引用FileReader 接口中提供的读取文件方法readAsDataURL(),在引用接口前,考虑到各浏览器对接口的兼容性不一样,JavaScript代码首先检测用户的浏览器是否支持FileReader对象,如果不支持,则提示出错信息。

接下来,在JavaScript代码中,遍历传回的上传文件集合,获取每个file对象,由于每个文件返回的数据块都不同,因此每次在读取文件前,必须先重构一个新的FileReader对象,然后将每个文件以数据URL的方式读入页面中,当读取成功时,触发onload事件,在该事件中,通过result属性获取文件读入页面中的URL地址,并将该地址与img元素进行绑定,最后
通过列表id为ulUpload的列表元素展示在页面中,从而实现图片文件上传预览的效果。详细实现过程见代码中加粗部分。
5.2.3使用FileReader()方法读取文本文件

除使用FileReader 接口中的readAsDataURL()方法读取图片文件、实现图片预览外,还可以借助接口提供的readAsText()方法,将文件以文本编码的方式进行读取,即可以读取上传文本文件的内容,其实现的方法与读取图片基本相似,仅是读取文件的方式不一样。
下面通过一个实例介绍使用readAsText ()方法读取文本文件内容的过程。
实例57使用readAsText ()方法读取文本文件内容
1. 功能描述

在页面表单中,新建一个file类型的input元素,用于获取上传的文本文件,当单击“选择文件”按钮,挑选了一个文本文件后,在页面中将显示该选择文本文件的内容。
2. 实现代码
在WebStorm中新建一个HTML页面57.html,加入代码如代码清单571所示。

代码清单571使用readAsText ()方法读取文本文件内容




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>使用readAsText()方法读取文本文件</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

<script type="text/javascript" language="jscript"

 src="Js/js7.js">

</script>

</head>

<body>







<form id="frmTmp">

<fieldset>

<legend>读取文本文件: </legend>

<input type="file" name="fleUpload" id="fleUpload" 

onChange="fileUpload_ReadTxtFile(this.files);"/>

<article id="artShow"></article>

</fieldset>

</form>

</body>

</html>




在实例57中,页面导入一个JavaScript文件js7.js,在该文件中,调用fileUpload_ReadTxtFile() 方法,该方法将文件以文本编码方式读取并返回页面,其实现的代码如代码清单572所示。

代码清单572实例57中的JavaScript文件js7.js的源码




// JavaScript Document

function $$(id) {

return document.getElementById(id);

}

//选择上传文件时调用的函数

function fileUpload_ReadTxtFile(f) {

//检测浏览器是否支持FileReader对象

if (typeof FileReader == 'undefined') {

alert("检测到您的浏览器不支持FileReader对象!");

}

var tmpFile = f[0];

var reader = new FileReader();

reader.readAsText(tmpFile);

reader.onload = function(e) {

$$("artShow").innerHTML = "<pre>" +

e.target.result + "</pre>";

}

}




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图57所示。


图57使用readAsText()方法读取文本文件时的效果


4. 源码分析
在本实例中,由于file类型的input文件上传元素,没有添加multiple属性,因此,单击“选择文件”按钮后,将返回单个file文件。
与实例56一样,JavaScript代码中,首先检测浏览器是否支持FileReader对象,如果支持,则重构一个新的FileReader对象,调用该对象的readAsText()方法,将文件以文本编码的方式读入页面中,然后通过result属性获取读入的内容,并将该内容赋值给id为artShow的元素,最后通过该元素将文本文件的内容显示在页面上。
5.2.4监听FileReader接口中的事件
在FileReader 接口中,提供了很多常用的事件,通过这些事件的触发,可以清晰地监听FileReader对象读取文件的详细过程,掌握这一过程中按顺序都触发了哪些事件,从而可以更加精确地定位每次读取文件时的事件先后顺序,为编写事件代码提供有力的支持。

经过反复测试,一个文件通过FileReader 接口中的方法正常读取时触发事件的先后顺序如图58所示。


图58使用readAsText()

方法读取顺序

针对文件读取时,事件触发先后顺序示意图,说明如下。
 大部分的文件读取过程,都集中在onprogress事件中,该事件耗时最长。
 如果文件在读取过程中出现异常或中止,那么,onprogress事件将结束,直接触发onerror或onabort事件,而不会触发onload事件。
 onload事件是文件读取成功时触发,而onloadend虽然也是文件操作成功时触发,但该事件不论文件读取是否成功,都将触发,因此,想要正确获取文件数据,必须在onload事件中编写代码。
下面通过一个实例介绍文件读取时触发事件的先后顺序。
实例58展示文件读取时触发事件的先后顺序
1. 功能描述

在页面的表单中,添加一个file类型的input元素,当用户单击“选择文件”按钮,并通过打开的窗口选取了一个文件后,页面中将展示读取文件过程中所触发事件的内容。
2. 实现代码
在WebStorm中新建一个HTML页面58.html,加入代码如代码清单581所示。

代码清单581展示文件读取时触发事件的先后顺序




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">







<title>展示文件读取时触发事件的先后顺序</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

<script type="text/javascript" language="jscript"

src="Js/js8.js">

</script>

</head>

<body>

<form id="frmTmp">

<fieldset>

<legend>文件读取事件的顺序: </legend>

<input type="file" name="fleUpload" id="fleUpload" 

onChange="fileUpload_ShowEvent(this.files);"/>

<p id="pStatus"></p>

</fieldset>

</form>

</body>

</html>




在实例58中,页面导入一个JavaScript文件js8.js,在该文件中,调用fileUpload_ShowEvent() 方法,该方法列出文件在正常读取过程中的全部事件,其实现的代码如代码清单582所示。

代码清单582实例58中的JavaScript文件js8.js的源码




// JavaScript Document

function $$(id) {

return document.getElementById(id);

}

//选择上传文件时调用的函数

function fileUpload_ShowEvent(f) {

if (typeof FileReader == 'undefined') {

alert("检测到您的浏览器不支持FileReader对象!");

}

var tmpFile = f[0];

var reader = new FileReader();

reader.readAsText(tmpFile);

reader.onload = function(e) {

$$("pStatus").style.display="block";

$$("pStatus").innerHTML = "数据读取成功!";

}

reader.onloadstart = function(e) {

$$("pStatus").style.display="block";

$$("pStatus").innerHTML = "开始读取数据...";

}

reader.onloadend = function(e) {

$$("pStatus").style.display="block";

$$("pStatus").innerHTML = "文件读取成功!";

}

reader.onprogress = function(e) {







$$("pStatus").style.display="block";

$$("pStatus").innerHTML = "正在读取数据...";

}

}




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图59所示。


图59显示文件读取过程中各事件执行的先后顺序


4. 源码分析
在本实例的页面中,单击“选择文件”按钮后,触发一个自定义的函数fileUpload_ShowEvent(),在该函数中,首先
检测浏览器是否支持FileReader 对象,如果不支持,则弹出错误提示信息,然后重新构造一个新的FileReader 对象,并对传回的文件以文本编码的方式读入页面; 最后列出文件在正常读取过程中将触发的4个事件,在每个事件中,先显示id为pStatus
的元素,后将事件的状态内容设置为该元素的文本内容; 当FileReader 对象执行readAsText()方法读取文件时,各个不同事件将按执行顺序被触发,设置的状态内容以动态的方式显示在id为pStatus的页面元素中。
5.2.5使用DataTransfer对象拖放上传图片文件

在HTML5中,借助于DataTransfer 接口提供的方法,可以实现浏览器与其他应用程序之间文件间的拖动,实现拖动数据的操作。虽然在HTML 4之前的版本中也支持拖放数据的操作,但该操作仅局限在整个浏览器中,而非浏览器之外的数据。
下面通过一个实例介绍使用DataTransfer对象拖放上传图片文件的过程。
实例59使用DataTransfer对象拖放上传图片文件
1. 功能描述

在页面的表单中,创建一个ul元素,用于接收并预览拖放过来的图片文件,当用户从计算机的文件夹中选择图片文件后,
可以以拖动的方式将文件放入该元素内,并以预览的方式进行显示。
2. 实现代码
在WebStorm中新建一个HTML页面59.html,加入代码如代码清单591所示。

代码清单591使用DataTransfer对象拖放上传图片文件




<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>拖放选择上传文件</title>

<link href="Css/css5.css" rel="stylesheet" type="text/css">

<script type="text/javascript" language="jscript"

src="Js/js9.js">

</script>

</head>

<body>

<form id="frmTmp">

<fieldset>

<legend>拖动选择文件: </legend>

<ul id="ulUpload" ondrop="dropFile (event)" 

ondragenter="return false"

ondragover="return false">

</ul>

</fieldset>

</form>

</body>

</html>




在实例59中,页面导入一个JavaScript文件js9.js,在该文件中,调用fileUpload_MoveFile() 方法,将拖动的文件数据放入DataTransfer对象,然后调取。其实现的代码如代码清单592所示。

代码清单592实例59中的JavaScript文件js9.js的源码




// JavaScript Document

function $$(id) {

return document.getElementById(id);

}

//选择上传文件时调用的函数

function fileUpload_MoveFile(f) {

//检测浏览器是否支持FileReader对象

if (typeof FileReader == 'undefined') {

alert("检测到您的浏览器不支持FileReader对象!");

}

for (var intI = 0; intI < f.length; intI++) {

var tmpFile = f[intI];

var reader = new FileReader();

reader.readAsDataURL(tmpFile);

reader.onload = (function(f1) {

return function(e) {








vareleSpan = document.createElement('span');

eleSpan.innerHTML = ['<img src="', 

e.target.result, 

'" title="',

f1.name, '"/>'].join('');

$$('ulUpload').insertBefore(eleSpan, null);

}

})(tmpFile);

}


}

function dropFile(e) {

//调用预览上传文件的方式

fileUpload_MoveFile(e.dataTransfer.files);

//停止事件的传播

e.stopPropagation();

//阻止默认事件的发生

e.preventDefault();

}




3. 页面效果
该页面在Chrome浏览器中执行的页面效果如图510所示。


图510显示拖放选择上传图片文件的效果


4. 源码分析
在本实例中,文件在从文件夹拖入页面目标元素的过程中,通过DataTransfer对象中的setData()方法保存数据,页面中的目标元素为了接收被保存的数据,在调用元素的拖放事件ondrop中调用了一个自定义的函数dropFile (),同时,为了确保目标元素顺利接收拖放文件,必须将目标元素的ondragenter与ondragover两个事件都返回false。详细实现过程见代码中加粗部分。

在自定义的函数dropFile ()中,先调用另一个自定义的函数fileUpload_MoveFile(),同时,要实现文件的拖放过程,还要在目标元素的拖放事件中,停止其他事件的传播并且关闭默认事件,其实现的过程如JavaScript 代码中自定义的函数dropFile ()所示。

在自定义的函数fileUpload_MoveFile()中,先从DataTransfer对象中获取被保存的文件集合,然后,遍历整个集合中的文件成员,获取每一个单独的文件,通过重构一个FileReader对象,调用该对象中的readAsDataURL(),将文件以数据地址的形式读入页面中,同时,创建页面元素span,将数据地址与img元素绑定,通过join()方法,写入span元素的内容中,最后,将全部获取的内容写入id为ulUpload的列表元素中,通过该元素展示在页面中。其实现的过程如JavaScript 代码中自定义的函数fileUpload_MoveFile ()所示。

有关DataTransfer对象更多的属性与方法,将在本书的第11章中有详细的介绍与运用。
小结
文件在HTML5中占有很重要的地位,在本节中,首先介绍选择单个与多个文件的实现方法,然后结合详细实例阐述选择文件后,以各种方式读取数据的过程。同时,讲解了如何在文件读取过程中,捕获出现的错误与异常的方法,为读者完整掌握HTML5中文件的使用打下扎实的理论与实践基础。