文件API
FileList对象与file对象
FileList
对象表示用户选择的文件列表。在HTML4中,file
控件内只允许放置一个文件, 但是到了H5中,通过添加multiple
属性,file
控件内允许一次放置多个文件。控件内的每一个用户选择的文件都是一个file
对象,而FileList
对象则为这些file
对象的列表,代表用户选择的所有文件。file
对象有两个属性,name
属性表示文件名, 不包括路径,lastModifiedDate
属性表示文件的最后修改日期。
<script language=javascript>
function ShowFileName(){
var file;
//document.getElementById("file").files返回FileList文件列表对象
for(var i=0;i<document.getElementById("file").files.length;i++){
//file对象为用户选择的单个文件
file = document.getElementById("file").files[i];
//此处您可以针对FileList文件列表中每个文件进行多种处理,本例中只弹出文件名
alert(file.name);
}
}
</script>
选择文件:
<input type="file" id="file" multiple size="80"/>
<input type="button" onclick="ShowFileName();" value="文件上传"/>
Blob对象
Blob
表示二进制原始数据,它提供一个slice
方法,可以通过该方法访问到字节内部的原始数据块。事实上,上面提到的file
对象也继承了这个Blob
对象.
Blob
对象有两个属性,size
属性表示一个Blob
对象的字节长度。type
属性表示Blob
的MIME类型,如果是未知类型,则返回一个空字符串。
function ShowFileType(){
var file;
//得到用户选择的第一个文件
file = document.getElementById("file").files[0];
var size=document.getElementById("size");
//显示文件字节长度
size.innerHTML=file.size;
var type=document.getElementById("type");
//显示文件类型
type.innerHTML=file.type;
}
</script>
选择文件:
<input type="file" id="file" />
<input type="button" value="显示文件信息" onclick="ShowFileType();"/><br/>
文件字节长度:<span id="size"></span><br/>
文件类型:<span id="type"></span>
对于图像类型的文件,Blob
对象的type
属性都是以image/
开头的,后跟图像类型,利用此特性我们可以在JS中判断用户选择的文件是否为图像文件,如果在批量上传时,只允许上传图像文件,可以利用该属性,如果用户选择的多个文件中有不是图像的文件时,可以弹出错误提示信息,并停止后面的文件上传,或者跳过这个文件,不将该文件上传。
function FileUpload(){
var file;
for(var i=0;i<document.getElementById("file").files.length;i++){
file = document.getElementById("file").files[i];
if(!/image\/\w+/.test(file.type)){
alert(file.name+"不是图像文件!");
break;
}
else{
//此处可加入文件上传的代码
alert(file.name+"文件已上传");
}
}
}
</script>
选择文件:
<input type="file" id="file" multiple/>
<input type="button" value="文件上传" onclick="FileUpload();"/>
另外,H5中已经对file
控件添加了accept
属性,企图让file
控件只能接受某种类型的文件,但是目前各主流浏览器对其的支持都只限于在打开文件选择窗口时,默认选择图像文件而己,如果选择其他类型文件,file
控件也能正常接受。
<input type="file" id="file" accept="image/*" />
FileReader接口
FileReader
接口主要用来把文件读入内存,并且读取文件中的数据。FileReader
接口提供 了一个异步API ,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据。
//检测浏览器是否支持FileReader接口
if(typeof FileReader=='undefined'){
alert("浏览器不支持FileReader接口")
}else{
var reader=new FileReader();
}
FileReader接口的方法
FileReader
接口拥有4个方法,其中3个用以读取文件,另一个用来将读取过程中断。无论读取成功或失败,方住并不会返回读取结果,这一结果存储在result
属性中。
readAsText
方法第二个参数是文本的编码方式,默认值为UTF-8。readAsBinaryString
这个方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。readAsDataURL
方法将文件读取为一串Data URL字符串,该方法事实上是将小文件以一种特殊格式的URL地址形式直接读入页面。这里的小文件通常是指图像与html
等格式的文件。
FileReader接口的事件
FileReader
接口还包含了一套完整的事件模型,用于捕获读取文件时的状态。
FileReader接口的使用示例
<script language=javascript>
var result=document.getElementById("result");
var file=document.getElementById("file");
if (typeof FileReader == 'undefined' ){
result.innerHTML = "<p>抱歉,你的浏览器不支持 FileReader</p>";
file.setAttribute( 'disabled','disabled' );
}
//将文件以Data URL形式进行读入页面
function readAsDataURL(){
//检查是否为图像文件
var file = document.getElementById("file").files[0];
if(!/image\/\w+/.test(file.type)){
alert("请确保文件为图像类型");
return false;
}
var reader = new FileReader();
//将文件以Data URL形式进行读入页面
reader.readAsDataURL(file);
reader.onload = function(e){
var result=document.getElementById("result");
//在页面上显示文件
result.innerHTML = '![]('+this.result+')'
}
}
//将文件以二进制形式进行读入页面
function readAsBinaryString(){
var file = document.getElementById("file").files[0];
var reader = new FileReader();
//将文件以二进制形式进行读入页面
reader.readAsBinaryString(file);
reader.onload = function(f){
var result=document.getElementById("result");
//在页面上显示二进制数据
result.innerHTML=this.result;
}
}
//将文件以文本形式进行读入页面
function readAsText(){
var file = document.getElementById("file").files[0];
var reader = new FileReader();
//将文件以文本形式进行读入页面
reader.readAsText(file);
reader.onload = function(f){
var result=document.getElementById("result");
//在页面上显示读入文本
result.innerHTML=this.result;
}
}
</script>
<p>
<label>请选择一个文件:</label>
<input type="file" id="file" />
<input type="button" value="读取图像" onclick="readAsDataURL()"/>
<input type="button" value="读取二进制数据" onclick="readAsBinaryString()"/>
<input type="button" value="读取文本文件" onclick="readAsText()"/>
</p>
<div name="result" id="result">
<!-- 这里用来显示读取结果 -->
</div>
在这个示例中,选取不同类型的文件,然后点击不同的按钮,浏览器会读取这些文件的各种数据,然后显示在画面中。当然您也可以选择不显示 ,而是直接提交到后端,然后保存到文件中或输送到数据库中。代码中fileReader
对象读取到的数据都保存在了result
属性中。
<script language=javascript>
var result=document.getElementById("result");
var input=document.getElementById("input");
if(typeof FileReader=='undefined'){
result.innerHTML = "<p class='warn'>抱歉,你的浏览器不支持 FileReader</p>";
input.setAttribute( 'disabled','disabled' );
}
function readFile(){
var file = document.getElementById("file").files[0];
var reader = new FileReader();
reader.onload = function(e){
result.innerHTML = '![]('+this.result+')'
alert("load");
}
reader.onprogress = function(e){
alert("progress");
}
reader.onabort = function(e){
alert("abort");
}
reader.onerror = function(e){
alert("error");
}
reader.onloadstart = function(e){
alert("loadstart");
}
reader.onloadend = function(e){
alert("loadend");
}
reader.readAsDataURL(file);
}
</script>
<p>
<label>请选择一个图像文件:</label>
<input type="file" id="file" />
<input type="button" value="显示图像" onclick="readFile()" />
</p>
<div name="result" id="result">
<!-- 这里用来显示读取结果 -->
</div>
在这个示例中,我们通过点击显示图像按钮在画面中读入一个图像文件,通过这个过程我们可以了解按顺序触发了哪些事件,并用提示信息的形式报出这些事件的名字。我们需要编写的代码主要都是在onprogress
事件中,譬如可以用H5中的新增元素progress
来显示大文件的读取完成百分比。
拖放
拖放步骤
1.将想要拖放的对象元素的draggable
属性设为true
,这样才能将该元素进行拖放。另外,img
元素与a
元素(必须指定href
)默认允许拖放。
2.编写与拖放有关的事件处理代码。
示例:
<title>拖放示例</title>
<script type="text/javascript">
function init() {
var source = document.getElementById("dragme");
var dest = document.getElementById("text");
// (1) 拖放开始
source.addEventListener("dragstart", function(ev) {
// 向dataTransfer对象追加数据
var dt = ev.dataTransfer;
dt.effectAllowed = 'all';
//(2) 拖动元素为dt.setData("text/plain", this.id);
dt.setData("text/plain", "你好");
}, false);
// (3) dragend:拖放结束
dest.addEventListener("dragend", function(ev) {
//不执行默认处理(拒绝被拖放)
ev.preventDefault();
}, false);
// (4) drop:被拖放
dest.addEventListener("drop", function(ev) {
// 从DataTransfer对象那里取得数据
var dt = ev.dataTransfer;
var text = dt.getData("text/plain");
dest.textContent += text;
//(5) 不执行默认处理(拒绝被拖放)
ev.preventDefault();
//停止事件传播
ev.stopPropagation();
}, false);
}
//(6) 设置页面属性,不执行默认处理(拒绝被拖放)
document.ondragover = function(e){e.preventDefault();};
document.ondrop = function(e){e.preventDefault();};
</script>
<body onload="init()">
<h1>简单拖放示例</h1>
<!-- (7) 把draggable属性设为true -->
<div id="dragme" draggable="true" style="width: 200px; border: 1px solid gray;">
请拖放
</div>
<div id="text" style="width: 200px; height: 200px; border: 1px solid gray;"></div>
</body>
代码解释:
- 开始拖动(
dragstart
)时,把要拖动的数据存入DataTransfer
对象(setData()
方法)。DataTransfer
对象专门用来存放拖放时要携带的数据,它可以被设置为拖动事件对象的dataTransfer
属性。setData
方法中的第一个参数为携带数据的数据种类的字符串,第二个参数为要携带的数据。第一个参数中表示数据种类的字符串里只能填入类似text/plain
或text/html
的表示MIME类型的文字,不能填入其它文字。 - 如果把
dt.setData("text/plain","你好");
改为dt.setData("text/plain",this.id);
,因为把被拖动元素的id
当成了参数,所以携带的数据就是被拖动元素中的数据了,因为浏览器在使用getData方法读取数据时会自动读取该元素中的数据。 - 针对拖放的目标元素,必须在
dragend
或dragover
事件内调用事件对象.preventDefault()
方法。因为默认情况下,拖放的目标元素是不允许接收元素的,为了把元素拖放到其中,必须把默认处理关闭掉。 - 目标元素接受到被拖放的元素后,执行
getData()
方能从DataTransfer
那里获得数据。getData()
方法的参数为setData()
方法中指定的数据种类。 - 要实现拖放过程,必须在目标元素的
drop
事件中关闭默认处理(拒绝被拖放),还必须设定整个页面为不执行默认处理(拒绝被拖放),否则目标元素不能接受被拖放的元素。 - 要使元素可以被拖放,首先必须把该元素的
draggable
属性设为true
。另外,为了让这个示例在所有支持拖放API的浏览器中都能正常运行,需要指定-webkit-user-drag:element
这种Webkit特有的属性。 - 因为这个示例中的数据种类使用了
text/plain
这个MIME类型,也可以从其他使用同样MIME类型的应用程序中把该类型的数据拖动到目标元素中。
支持拖动处理的MIME的类型为:
-
text/plain
:文本文字 -
text/html
:HTML文字 -
text/xml
:XML文字 -
text/uri-list
:URL列表,每个URL为一行
DataTransfer对象的属性与万法
如果DataTransfer
对象的属性和方能使用得好,可以实现定制拖放图标,让它只支持特定拖放(如拷贝/移动) 等,甚至可以实现更复杂的拖放操作。
属性/方法 | 描述 |
---|---|
dropEffect属性 | 表示拖放操作的视觉效果,允许对其进行值的设定。该效果必须在用effectAllowed属性指定的允许的视觉效果的范围内,允许指定的值为none、copy、link、move |
effectAllowed属性 | 用来指定当前元素能被拖放时所允许的视觉效果。可以指定的值为none、copy、copyLink、copyMove、link、linkMove、move、all、unintialize |
types属性 | 存入数据的种类,字符串的伪数组 |
void clearDaata(DOMString format)方法 | 消除DataTransfer对象中存放的数据。如果省略参数format,则消除全部数据 |
void setData(DOMString format、DOMString data) | 向DataTransfer对象内存入数据 |
DOMString getData(DOMString format) | 从DataTransfer对象中读数据 |
void setDragImage(Element image,long x,long y) | 用img元素来设置拖放图标(部分浏览器可用canvas等其他元素) |
setData
方法在拖放开始时向dataTransfer
对象中存入数据,它用types
属性来指定数据的MIME类型。getData
方法在拖动结束时读取dataTransfer
对象中的数据。clearData
方法可以用来清除DataTransfer
对象内的数据。
设定拖放时的视觉效果
dropEffect
属性与effectAllowed
属性结合起来可以设定拖放时的视觉效果。effectAllowed
属性表示当一个元素被拖动时所允许的视觉效果,一般在ondragstart
事件中设定,允许设定的值为none、copy、copyLink、copyMove、link、linkMove、move、all、unintialize
。dropEffect
属性表示实际拖放时的视觉效果, 一般在ondragover
事件中指定,允许设定的值为none、copy、link、move
。dropEffect
属性所表示的实际视觉数果必须在effectAllowed
属性所表示的允许的视觉效果范围内。规则如所示。
- 如果
effectAllowed
属性设定为none
,则不允许拖放元素 - 如果
dropEffect
属性设定为none
,则不允许被拖放到目标元素中 - 如果
effectAllowed
属性设定为all
或不设定,则dropEffect
属性允许被设定为任何值,并且按指定的视觉效果进行显示 - 如果
effectAllowed
属性设定为具体效果(不为none、all
) ,dropEffect
属性也设定了具体视觉效果,则两个具体效果值必须完全相等,否则不允许将被拖放元素拖放到目标元素中
source.addEventListener( "dragstart" , function(ev){
var dt = ev.dataTransfer;
//设定effectAllowed属性
dt.effectAllowed ='copy';
dt.setData("text/plain","你好") ;
}, false);
dest.addEventListener( "dragover" , function (ev){
var dt = ev.dataTransfer;
//设定dropEffect属性
dt.dropEffect ='copy';
ev.preventDefault();
}, false);
自定义拖放图标
H5中允许自定义拖放图标——指的是在用鼠标拖动元素的过程中,位于鼠标指针下部的小图标。
DataTransfer
对象有一个setDragImage
方法,该方法有三个参数,第一个参数image
设定为拖放图标的图标元素,第二个参数x
为拖放图标离鼠标指针的x
轴方向的位移量,第三个参数y
为拖放图标离鼠标指针的y
轴方向的位移量。
//创建图标元素
var dragIcon = document.createElement('img');
//设定图标来源
dragIcon.src = 'http://twivatar.orq/twitter/mini';
source.addEventListener("dragstart", function(ev) {
var dt = ev.dataTransfer;
//设定自定义图标
dt.setDragImage(dragIcon, -10, -10);
dt.setData("text/plain","aaa");
}, false);