H5文件與拖放API

文件API

FileList對象與file對象

FileList對象表示用戶選擇的文件列表扇雕。在HTML4中吓肋,file控件內(nèi)只允許放置一個文件签孔, 但是到了H5中地熄,通過添加multiple屬性华临,file控件內(nèi)允許一次放置多個文件《丝迹控件內(nèi)的每一個用戶選擇的文件都是一個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表示二進制原始數(shù)據(jù)漾岳,它提供一個slice方法轰绵,可以通過該方法訪問到字節(jié)內(nèi)部的原始數(shù)據(jù)塊。事實上尼荆,上面提到的file對象也繼承了這個Blob對象.
Blob對象有兩個屬性左腔,size屬性表示一個Blob對象的字節(jié)長度掉缺。type屬性表示Blob的MIME類型攘须,如果是未知類型,則返回一個空字符串岖赋。

function ShowFileType(){
    var file;
    //得到用戶選擇的第一個文件 
    file = document.getElementById("file").files[0];
    var size=document.getElementById("size");
    //顯示文件字節(jié)長度
    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/>
文件字節(jié)長度:<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中已經(jīng)對file控件添加了accept屬性念逞,企圖讓file控件只能接受某種類型的文件,但是目前各主流瀏覽器對其的支持都只限于在打開文件選擇窗口時县昂,默認選擇圖像文件而己肮柜,如果選擇其他類型文件陷舅,file控件也能正常接受倒彰。

<input type="file" id="file" accept="image/*" />

FileReader接口

FileReader接口主要用來把文件讀入內(nèi)存,并且讀取文件中的數(shù)據(jù)莱睁。FileReader接口提供 了一個異步API 待讳,使用該API可以在瀏覽器主線程中異步訪問文件系統(tǒng),讀取文件中的數(shù)據(jù)仰剿。

//檢測瀏覽器是否支持FileReader接口
if(typeof FileReader=='undefined'){
    alert("瀏覽器不支持FileReader接口")
}else{
    var reader=new FileReader();
}
FileReader接口的方法

FileReader接口擁有4個方法创淡,其中3個用以讀取文件,另一個用來將讀取過程中斷南吮。無論讀取成功或失敗琳彩,方住并不會返回讀取結(jié)果,這一結(jié)果存儲在result屬性中部凑。

FileReader接口的方法

readAsText方法第二個參數(shù)是文本的編碼方式露乏,默認值為UTF-8。readAsBinaryString這個方法將文件讀取為二進制字符串涂邀,通常我們將它傳送到后端瘟仿,后端可以通過這段字符串存儲文件。readAsDataURL方法將文件讀取為一串Data URL字符串比勉,該方法事實上是將小文件以一種特殊格式的URL地址形式直接讀入頁面劳较。這里的小文件通常是指圖像與html等格式的文件。

FileReader接口的事件

FileReader接口還包含了一套完整的事件模型浩聋,用于捕獲讀取文件時的狀態(tài)观蜗。

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");
        //在頁面上顯示二進制數(shù)據(jù)
        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="讀取二進制數(shù)據(jù)" onclick="readAsBinaryString()"/>
    <input type="button" value="讀取文本文件" onclick="readAsText()"/>
</p> 
<div name="result" id="result">
      <!-- 這里用來顯示讀取結(jié)果 -->
</div>

在這個示例中衣洁,選取不同類型的文件嫂便,然后點擊不同的按鈕,瀏覽器會讀取這些文件的各種數(shù)據(jù)闸与,然后顯示在畫面中毙替。當(dāng)然您也可以選擇不顯示 岸售,而是直接提交到后端,然后保存到文件中或輸送到數(shù)據(jù)庫中厂画。代碼中fileReader對象讀取到的數(shù)據(jù)都保存在了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">
<!-- 這里用來顯示讀取結(jié)果 -->
</div>

在這個示例中袱院,我們通過點擊顯示圖像按鈕在畫面中讀入一個圖像文件屎慢,通過這個過程我們可以了解按順序觸發(fā)了哪些事件,并用提示信息的形式報出這些事件的名字忽洛。我們需要編寫的代碼主要都是在onprogress事件中腻惠,譬如可以用H5中的新增元素progress來顯示大文件的讀取完成百分比。

拖放

拖放步驟

1.將想要拖放的對象元素的draggable屬性設(shè)為true欲虚,這樣才能將該元素進行拖放集灌。另外,img元素與a元素(必須指定href)默認允許拖放复哆。
2.編寫與拖放有關(guān)的事件處理代碼欣喧。

拖放的相關(guān)事件

示例:

<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對象追加數(shù)據(jù)
        var dt = ev.dataTransfer;
        dt.effectAllowed = 'all';    
       //(2) 拖動元素為dt.setData("text/plain", this.id); 
        dt.setData("text/plain", "你好"); 
    }, false);
    // (3) dragend:拖放結(jié)束
    dest.addEventListener("dragend", function(ev) {
        //不執(zhí)行默認處理(拒絕被拖放)
        ev.preventDefault();
    }, false);
    // (4) drop:被拖放
    dest.addEventListener("drop", function(ev) {
        // 從DataTransfer對象那里取得數(shù)據(jù)
        var dt = ev.dataTransfer;
        var text = dt.getData("text/plain");
        dest.textContent += text;
        //(5) 不執(zhí)行默認處理(拒絕被拖放)
        ev.preventDefault();
        //停止事件傳播
        ev.stopPropagation();
    }, false);
}
//(6) 設(shè)置頁面屬性,不執(zhí)行默認處理(拒絕被拖放)
document.ondragover = function(e){e.preventDefault();};
document.ondrop = function(e){e.preventDefault();};
</script>

<body onload="init()">
<h1>簡單拖放示例</h1>
<!-- (7) 把draggable屬性設(shè)為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)時梯找,把要拖動的數(shù)據(jù)存入DataTransfer對象(setData()方法)唆阿。DataTransfer對象專門用來存放拖放時要攜帶的數(shù)據(jù),它可以被設(shè)置為拖動事件對象的dataTransfer屬性锈锤。setData方法中的第一個參數(shù)為攜帶數(shù)據(jù)的數(shù)據(jù)種類的字符串驯鳖,第二個參數(shù)為要攜帶的數(shù)據(jù)。第一個參數(shù)中表示數(shù)據(jù)種類的字符串里只能填入類似text/plaintext/html的表示MIME類型的文字久免,不能填入其它文字浅辙。
  • 如果把dt.setData("text/plain","你好");改為dt.setData("text/plain",this.id);,因為把被拖動元素的id當(dāng)成了參數(shù)妄壶,所以攜帶的數(shù)據(jù)就是被拖動元素中的數(shù)據(jù)了摔握,因為瀏覽器在使用getData方法讀取數(shù)據(jù)時會自動讀取該元素中的數(shù)據(jù)。
  • 針對拖放的目標元素丁寄,必須在dragenddragover事件內(nèi)調(diào)用事件對象.preventDefault()方法氨淌。因為默認情況下,拖放的目標元素是不允許接收元素的伊磺,為了把元素拖放到其中盛正,必須把默認處理關(guān)閉掉。
  • 目標元素接受到被拖放的元素后屑埋,執(zhí)行getData()方能從DataTransfer那里獲得數(shù)據(jù)豪筝。getData()方法的參數(shù)為setData()方法中指定的數(shù)據(jù)種類。
  • 要實現(xiàn)拖放過程,必須在目標元素的drop事件中關(guān)閉默認處理(拒絕被拖放)续崖,還必須設(shè)定整個頁面為不執(zhí)行默認處理(拒絕被拖放)敲街,否則目標元素不能接受被拖放的元素。
  • 要使元素可以被拖放严望,首先必須把該元素的draggable屬性設(shè)為true多艇。另外,為了讓這個示例在所有支持拖放API的瀏覽器中都能正常運行像吻,需要指定-webkit-user-drag:element這種Webkit特有的屬性峻黍。
  • 因為這個示例中的數(shù)據(jù)種類使用了text/plain這個MIME類型,也可以從其他使用同樣MIME類型的應(yīng)用程序中把該類型的數(shù)據(jù)拖動到目標元素中拨匆。

支持拖動處理的MIME的類型為:

  • text/plain:文本文字
  • text/html:HTML文字
  • text/xml:XML文字
  • text/uri-list:URL列表姆涩,每個URL為一行

DataTransfer對象的屬性與萬法

如果DataTransfer對象的屬性和方能使用得好,可以實現(xiàn)定制拖放圖標惭每,讓它只支持特定拖放(如拷貝/移動) 等骨饿,甚至可以實現(xiàn)更復(fù)雜的拖放操作。

屬性/方法 描述
dropEffect屬性 表示拖放操作的視覺效果洪鸭,允許對其進行值的設(shè)定样刷。該效果必須在用effectAllowed屬性指定的允許的視覺效果的范圍內(nèi)仑扑,允許指定的值為none览爵、copy、link镇饮、move
effectAllowed屬性 用來指定當(dāng)前元素能被拖放時所允許的視覺效果蜓竹。可以指定的值為none储藐、copy俱济、copyLink、copyMove钙勃、link蛛碌、linkMove、move辖源、all蔚携、unintialize
types屬性 存入數(shù)據(jù)的種類,字符串的偽數(shù)組
void clearDaata(DOMString format)方法 消除DataTransfer對象中存放的數(shù)據(jù)克饶。如果省略參數(shù)format酝蜒,則消除全部數(shù)據(jù)
void setData(DOMString format、DOMString data) 向DataTransfer對象內(nèi)存入數(shù)據(jù)
DOMString getData(DOMString format) 從DataTransfer對象中讀數(shù)據(jù)
void setDragImage(Element image,long x,long y) 用img元素來設(shè)置拖放圖標(部分瀏覽器可用canvas等其他元素)

setData方法在拖放開始時向dataTransfer對象中存入數(shù)據(jù)矾湃,它用types屬性來指定數(shù)據(jù)的MIME類型亡脑。getData方法在拖動結(jié)束時讀取dataTransfer對象中的數(shù)據(jù)。clearData方法可以用來清除DataTransfer對象內(nèi)的數(shù)據(jù)。

設(shè)定拖放時的視覺效果

dropEffect屬性與effectAllowed屬性結(jié)合起來可以設(shè)定拖放時的視覺效果霉咨。effectAllowed屬性表示當(dāng)一個元素被拖動時所允許的視覺效果蛙紫,一般在ondragstart事件中設(shè)定,允許設(shè)定的值為none途戒、copy惊来、copyLink、copyMove棺滞、link裁蚁、linkMove、move继准、all枉证、unintializedropEffect屬性表示實際拖放時的視覺效果移必, 一般在ondragover事件中指定室谚,允許設(shè)定的值為none、copy崔泵、link秒赤、movedropEffect屬性所表示的實際視覺數(shù)果必須在effectAllowed屬性所表示的允許的視覺效果范圍內(nèi)憎瘸。規(guī)則如所示入篮。

  • 如果effectAllowed屬性設(shè)定為none,則不允許拖放元素
  • 如果dropEffect屬性設(shè)定為none幌甘,則不允許被拖放到目標元素中
  • 如果effectAllowed屬性設(shè)定為all或不設(shè)定潮售,則dropEffect屬性允許被設(shè)定為任何值,并且按指定的視覺效果進行顯示
  • 如果effectAllowed屬性設(shè)定為具體效果(不為none锅风、all) 酥诽,dropEffect屬性也設(shè)定了具體視覺效果,則兩個具體效果值必須完全相等皱埠,否則不允許將被拖放元素拖放到目標元素中
source.addEventListener( "dragstart" , function(ev){
    var dt = ev.dataTransfer;
    //設(shè)定effectAllowed屬性 
    dt.effectAllowed ='copy'; 
    dt.setData("text/plain","你好") ;
}, false);
dest.addEventListener( "dragover" , function (ev){
    var dt = ev.dataTransfer;
    //設(shè)定dropEffect屬性
    dt.dropEffect ='copy'; 
    ev.preventDefault();
}, false);

自定義拖放圖標

H5中允許自定義拖放圖標——指的是在用鼠標拖動元素的過程中肮帐,位于鼠標指針下部的小圖標。
DataTransfer對象有一個setDragImage方法边器,該方法有三個參數(shù)训枢,第一個參數(shù)image設(shè)定為拖放圖標的圖標元素,第二個參數(shù)x為拖放圖標離鼠標指針的x軸方向的位移量饰抒,第三個參數(shù)y為拖放圖標離鼠標指針的y軸方向的位移量肮砾。

//創(chuàng)建圖標元素
var dragIcon = document.createElement('img');
//設(shè)定圖標來源
dragIcon.src = 'http://twivatar.orq/twitter/mini'; 
source.addEventListener("dragstart", function(ev) {
var dt = ev.dataTransfer;
//設(shè)定自定義圖標 
dt.setDragImage(dragIcon, -10, -10); 
dt.setData("text/plain","aaa");
}, false);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市袋坑,隨后出現(xiàn)的幾起案子仗处,更是在濱河造成了極大的恐慌眯勾,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婆誓,死亡現(xiàn)場離奇詭異吃环,居然都是意外死亡,警方通過查閱死者的電腦和手機洋幻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門郁轻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人文留,你說我怎么就攤上這事好唯。” “怎么了燥翅?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵骑篙,是天一觀的道長。 經(jīng)常有香客問我森书,道長靶端,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任凛膏,我火速辦了婚禮杨名,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猖毫。我一直安慰自己台谍,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布鄙麦。 她就那樣靜靜地躺著典唇,像睡著了一般镊折。 火紅的嫁衣襯著肌膚如雪胯府。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天恨胚,我揣著相機與錄音骂因,去河邊找鬼。 笑死赃泡,一個胖子當(dāng)著我的面吹牛寒波,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播升熊,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼俄烁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了级野?” 一聲冷哼從身側(cè)響起页屠,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辰企,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體风纠,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年牢贸,在試婚紗的時候發(fā)現(xiàn)自己被綠了竹观。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡潜索,死狀恐怖臭增,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竹习,我是刑警寧澤速址,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站由驹,受9級特大地震影響芍锚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蔓榄,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一并炮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甥郑,春花似錦逃魄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至勉躺,卻和暖如春癌瘾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背饵溅。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工妨退, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜕企。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓咬荷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親轻掩。 傳聞我的和親對象是個殘疾皇子幸乒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容