[轉]文件file屬性詳解

    不能直接訪問用戶計算機中的文件,一直都是Web應用開發中的一大障礙。2000年之前,處理文件的惟一方式就是在表單中加入<input type="file">字段,僅此而已。FileAPI(文件API)的宗旨是爲Web開發人員提供一種安全的方式,以便在客戶端訪問用戶計算機中的文件,並更好地對這些文件執行操做。本文將詳細介紹文件File APIphp

  [注意]IE9-瀏覽器不支持html

File

  File API在表單中的文件輸入字段的基礎上,又添加了一些直接訪問文件信息的接口。HTML5在DOM中爲文件輸入元素添加了一個files集合。在經過文件輸入字段選擇了一或多個文件時,files集合中將包含一組File對象,每一個File對象對應着一個文件。每一個File對象都有下列只讀屬性瀏覽器

  name:本地文件系統中的文件名安全

  size:文件的字節大小服務器

  type:字符串,文件的MIME類型app

  lastModifiedDate:字符串,文件上一次被修改的時間異步

  經過偵聽change事件並讀取files集合就能夠知道選擇的每一個文件的信息svg

複製代碼
<input type="file" id="file1">
<div id="result"></div>
<script>
file1.onchange = function(){
    var data = file1.files[0];
    result.innerHTML = '類型:' + data.type  + '<br>大小:' + data.size + '(字節)<br>名稱:' + data.name + '<br>修改時間:' + data.lastModifiedDate;
}
</script>
複製代碼

 

【隱藏文件input】

  現代瀏覽器支持隱藏掉默認的的文件輸入框<input>元素,使用自定義的界面來充當打開文件選擇對話框的按鈕。實現起來很簡單,只須要使用樣式display:none把本來的文件輸入框隱藏掉,而後在須要的時候調用它的click()方法就好了函數

  [注意]IE9-瀏覽器不支持post

複製代碼
<input type="file" id="file1" style="display:none">
<button id="btn">按鈕</button>
<div id="result"></div>
<script>
btn.onclick = function(){
    file1.click();
}
file1.onchange = function(){
    result.innerHTML = file1.files[0].name;
}
</script>
複製代碼

 

FileReader

  File API的功能還不止於此,經過它提供的FileReader類型甚至還能夠讀取文件中的數據

【構造函數】

  使用FileReader()構造函數來建立一個FileReader對象

var reader = new FileReader();

【屬性】

  error:表示在讀取文件時發生的錯誤(只讀)

  readyState:代表FileReader對象的當前狀態,值爲狀態常量中的一個(只讀)

  狀態常量有如下三個

常量名      值    描述
EMPTY      0    尚未加載任何數據
LOADING    1    數據正在被加載
DONE       2    已完成所有的讀取請求

  result:表示讀取到的文件內容,這個屬性只在讀取操做完成以後纔有效,而且數據的格式取決於讀取操做是由哪一個方法發起的(只讀)

【方法】

  FileReader類型實現的是一種異步文件讀取機制。能夠把FileReader想象成XMLHttpRequest,區別只是它讀取的是文件系統,而不是遠程服務器。爲了讀取文件中的數據,FileReader提供了以下幾個方法

  abort():停止該讀取操做

  readAsText(file或Blob,encoding):以純文本形式讀取File或Blob對象的內容,將讀取到的文本保存在result屬性中。第二個參數(可選)用於指定編碼類型,默認爲UTF-8

  readAsDataURL(file或Blob):讀取File或Blob對象的內容,並將文件以數據URI(進行Base64編碼)的形式保存在result屬性中

  readAsBinaryString(file或Blob):讀取File或Blob對象的內容,並將一個字符串保存在result屬性中,字符串中的每一個字符表示一字節

  readAsArrayBuffer(file或Blob):讀取File或Blob對象的內容,並將一個包含文件內容的ArrayBuffer保存在result屬性中

  [注意]IE瀏覽器不支持readAsBinaryString()方法

  這些讀取文件的方法爲靈活地處理文件數據提供了極大便利。例如,能夠讀取圖像文件並將其保存爲數據URI,以便將其顯示給用戶,或者爲了解析方便,能夠將文件讀取爲文本形式

【事件】

  因爲讀取過程是異步的,所以FileReader也提供了幾個事件

  onabort:當讀取操做被停止時調用

  onerror:當讀取操做發生錯誤時調用

  onload:當讀取操做成功完成時調用

  onloadend:當讀取操做完成時調用,不論是成功仍是失敗。該處理程序在onload或者onerror以後調用

  onloadstart:當讀取操做將要開始以前調用

  onprogress:在讀取數據過程當中週期性調用

  在正常狀況下,讀取文件時,首先觸發loadstart事件,此時的readyState爲1,result爲空

  接着,每過50ms左右,就會觸發一次progress事件,經過事件對象能夠得到與XHR的progress事件相同的信息(屬性):lengthComputable、loaded和total。另外,儘管可能沒有包含所有數據,但每次progress事件中均可以經過FileReader的result屬性讀取到文件內容,readyState仍然是1

  當文件讀取完成時,觸發load事件,此時的readyState爲2,result爲文件內容;若是發生了error事件,就不會發生load事件

複製代碼
<input type="file" id="file1">
<div id="result"></div>
<script>
/*
[loadstart]readyState:1;result:
[progress]readyState:1;result:h3{color: #F44336;}
[load]readyState:2;result:h3{color: #F44336;}
[loadend]readyState:2;result:h3{color: #F44336;}
*/
file1.onchange = function(){
    var reader = new FileReader();
    reader.readAsText(file1.files[0]);
    reader.onloadstart = function(e){
        console.log('[loadstart]readyState:' + reader.readyState + ';result:' + reader.result);
    }
    reader.onload = function(e){
        console.log('[load]readyState:' + reader.readyState + ';result:' + reader.result);
    }
    reader.onloadend = function(e){
        console.log('[loadend]readyState:' + reader.readyState + ';result:' + reader.result);
    }
    reader.onprogress = function(e){
        console.log('[progress]readyState:' + reader.readyState + ';result:' + reader.result);
    }
}
</script>
複製代碼

  因爲種種緣由沒法讀取文件,就會觸發error事件。觸發error事件時,相關的信息將保存到FileReader的error屬性中。這個屬性中將保存一個對象,該對象只有一個屬性code,即錯誤碼。這個錯誤碼是1表示未找到文件,是2表示安全性錯誤,是3表示讀取中斷,是4表示文件不可讀,是5表示編碼錯誤

reader.onerror = function(){
    output.innerHTML = "Could not read file, error code is " + reader.error.code;
}; 

  若是想中斷讀取過程,能夠調用abort()方法,這樣就會觸發abort事件

  在觸發load、error或abort事件後,會觸發另外一個事件loadend。loadend事件發生就意味着已經讀取完整個文件,或者讀取時發生了錯誤,或者讀取過程被中斷

 

重要的縮略圖

  使用FileReader對象的 readAsDataURL() 方法完成對文件的讀取,再經過 File對象的 type屬性 篩選出圖片

複製代碼
<img id="uploadPreview" style="width: 100px; height: 100px;" src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%3F%3E%0A%3Csvg%20width%3D%22153%22%20height%3D%22153%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%0A%20%3Cg%3E%0A%20%20%3Ctitle%3ENo%20image%3C/title%3E%0A%20%20%3Crect%20id%3D%22externRect%22%20height%3D%22150%22%20width%3D%22150%22%20y%3D%221.5%22%20x%3D%221.500024%22%20stroke-width%3D%223%22%20stroke%3D%22%23666666%22%20fill%3D%22%23e1e1e1%22/%3E%0A%20%20%3Ctext%20transform%3D%22matrix%286.66667%2C%200%2C%200%2C%206.66667%2C%20-960.5%2C%20-1099.33%29%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22middle%22%20font-family%3D%22Fantasy%22%20font-size%3D%2214%22%20id%3D%22questionMark%22%20y%3D%22181.249569%22%20x%3D%22155.549819%22%20stroke-width%3D%220%22%20stroke%3D%22%23666666%22%20fill%3D%22%23000000%22%3E%3F%3C/text%3E%0A%20%3C/g%3E%0A%3C/svg%3E" alt="Image preview" />
<input type="file" id="file1" style="display:none">
<button id="btn">選擇圖片</button>
<span id="msgName"></span>
<script>
btn.onclick = function(){
    file1.click();
}
file1.onchange = function(){
    var file = file1.files[0];
    //若是一個文件被選中
    if(file){
        //一張圖片被選中
        if (/image/.test(file.type)){
            var reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = function(){
                uploadPreview.src = reader.result;
                msgName.innerHTML = file.name;
            }
        //其餘格式文件被選中
        } else {
            alert("You must select a valid image file!");
        }                
    }    
}
</script>
複製代碼

 demo以下

<input type="file" id="file1" style="display:none">
  <button id="btn">按鈕</button>
  <div id="result"></div>
<script>
btn.onclick = function() {
  file1.click();
}
file1.onchange = function() {
  var reader = new FileReader();
  reader.readAsDataURL(file1.files[0]);
  reader.onload = function(e){
     var img =new Image();
     console.log(e.target.result);
     img.src = e.target.result;
     document.body.appendChild(img);
  }
}
</script>

輸出 src 以下:

 

Blob URL

  使用Blob URL,也能夠用來顯示縮略圖

複製代碼
<input id="file1" type="file" accept="image/gif,image/jpeg,image/jpg,image/png,image/x-icon"  style="display:none">
<button id="btn">選擇圖片</button>
<div id="fileList"></div>
<script>
btn.onclick = function(){file1.click();}
//保存圖片的名稱
var dataArr = [];
file1.onchange = function(){
    var file = file1.files[0];
    //若是一個文件被選中
    if(file){
        var name = file.name;
        var id = name.split('.').join('_');
        //檢測圖片是否已經被存儲過
        if(dataArr.indexOf(id) > -1){
            //將保存過的圖片轉移到最下方
            fileList.appendChild(document.getElementById(id));
        }else{
            if(/image/.test(file.type)){
                dataArr.push(id);
                var img = document.createElement('img');
                img.onload = function(){
                    URL.revokeObjectURL(img.src);
                }
                img.src= URL.createObjectURL(file);
                img.height = 60;
                var oDiv = document.createElement('div');
                oDiv.id = id;
                var oSpan = document.createElement('span');
                oSpan.innerHTML = name + ":" + file.size + " bytes";
                oDiv.appendChild(img);
                oDiv.appendChild(oSpan);
                fileList.appendChild(oDiv);                
            }
        }
    }    
}
</script>
複製代碼

demo 以下:

 <input type="file" id="file1" style="display:none">
  <button id="btn">按鈕</button>
  <div id="result"></div>
<script>
btn.onclick = function() {
  file1.click();
}
file1.onchange = function() {
  var src = URL.createObjectURL(file1.files[0]);
  console.log(src);
  var img = new Image();
  img.src = src;
  img.width = 100;
  img.height = 100;
  document.body.appendChild(img);
}
</script>

輸出 src 以下:

文件內容

  readAsText() 能夠以字符串形式讀取並顯示文件內容

複製代碼
<input id="file1" type="file"  style="display:none">
<button id="btn">選擇文件</button>
<div id="fileData" style="border:1px solid black;width:300px;overflow:auto"></div>
<script>
btn.onclick = function(){file1.click();}
file1.onchange = function(){
    var file = file1.files[0];
    //若是一個文件被選中
    if(file){
        var reader = new FileReader();
        reader.readAsText(file);
        reader.onload = function(){
            fileData.innerHTML = reader.result;
        }
    }         
}
</script>
複製代碼

 

拖放選擇

  圍繞讀取文件信息,結合使用HTML5拖放API和文件API,可以創造出使人矚目的用戶界面:在頁面上建立了自定義的放置目標以後,你能夠從桌面上把文件拖放到該目標。與拖放一張圖片或者一個連接相似,從桌面上把文件拖放到瀏覽器中也會觸發drop事件。並且能夠在event.dataTransfer.files中讀取到被放置的文件,固然此時它是一個File對象,與經過文件輸入字段取得的File對象同樣

  [注意]IE9-瀏覽器不支持event.dataTransfer

  從電腦上選擇一個圖片文件,並拖放到網頁中指定區域,圖片縮略圖將顯示到網頁上

複製代碼
<div id="targetArea" style="height:50px;line-height:50px;width:210px;background:lightblue;">請將圖片文件拖放到該區域內</div>
<div id="result"></div>
<script>
function addEvent(target,type,handler){
    if(target.addEventListener){
        target.addEventListener(type,handler,false);
    }else{
        target.attachEvent('on'+type,function(event){
            return handler.call(target,event);
        });
    }
}
function preventDefault(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
}
addEvent(document,'dragover',preventDefault);
addEvent(document,'drop',preventDefault);
addEvent(targetArea,'dragenter',preventDefault);
addEvent(targetArea,'dragover',preventDefault);
addEvent(targetArea,'dragleave',preventDefault);
addEvent(targetArea,'drop',preventDefault);
targetArea.ondragenter = function(e){this.style.outline = "1px solid black";}
targetArea.ondragleave = function(e){this.style.outline = "";}
targetArea.ondrop = function(e){
    e = e || event;
    this.style.outline = "";
    var file = e.dataTransfer.files[0];
    if(file){
        //一張圖片被選中
        if (/image/.test(file.type)){
            var reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = function(){
                var oDiv = document.createElement('div');
                oDiv.id = file.name.split('.').join('_')
                var img = new Image();
                img.src = reader.result;
                img.height = 60;
                var oName = document.createElement('span');
                oName.innerHTML = file.name;
                var oDel = document.createElement('button');
                oDel.innerHTML = '刪除';
                oDel.onclick = function(){
                    result.removeChild(oDiv);
                }               
                oDiv.appendChild(img);
                oDiv.appendChild(oName);
                oDiv.appendChild(oDel);
                result.appendChild(oDiv);
            }
        //其餘格式文件被選中
        } else {
            alert("You must select a valid image file!");
        }          
    }
}
</script>
複製代碼

 

文件進度

  使用onprogress事件的loaded和total屬性,能夠實現文件進度顯示

複製代碼
<input id="file1" type="file"  style="display:none">
<button id="btn">選擇文件</button>
<div id="fileData"></div>
<script>
btn.onclick = function(){file1.click();}
file1.onchange = function(){
    var file = file1.files[0];
    //若是一個文件被選中
    if(file){
        var reader = new FileReader();
        reader.readAsText(file);
        reader.onprogress = function(e){
            e = e || event;
            fileData.innerHTML = '文件進度爲:' + e.loaded + '/' + e.total;
        }
    }         
}
</script>
複製代碼

 

文件上傳

方法一:使用表單提交實現文件上傳

  文件上傳最基本的方法是使用HTML表單選擇本地文件進行上傳,在form表單中經過<input type="file">標記選擇本地文件。而且,必須在<form>元素中將enctype設置爲"multipart/form-data",將method設置爲"post"

  另外,須要在<form>表單中設置一個hidden類型的input框,其中name值爲MAX_FILE_SIZE的隱藏值域,經過設置其value值限制上傳文件的大小

<form action="pp.php" method="post" enctype="multipart/form-data">
    <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
    <input type="file" name="file1">
    <button>上傳文件</button>
</form>

方法二:使用FormData實現文件上傳

  建立一個FormData()對象,經過它調用append()方法並傳入相應的File對象做爲參數。而後,再把FormData對象傳遞給XHR的send()方法

  [注意]IE9-瀏覽器不支持使用FormData()上傳文件

複製代碼
<input type="file" name="file1" id="file1">
<div id="result"></div>
<script>
var oFile = document.getElementById('file1');
oFile.onchange = function(e){
    //建立xhr對象
    var xhr;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    };
    var data = new FormData();
    data.append('file',oFile.files[0])
    //異步接受響應
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            if(xhr.status == 200){
                //實際操做
                result.innerHTML = xhr.responseText;
            }
        }
    }
    //發送請求
    xhr.open('post','pp.php',true);
    xhr.send(data);
}
</script>
複製代碼

方法三:使用File API實現文件上傳

  經過File API傳送二進制文件

  [注意]IE9-瀏覽器不支持

複製代碼
<input type="file" name="file1" id="file1">
<div id="result"></div>
<script>
var oFile = document.getElementById('file1');
oFile.onchange = function(e){
    //建立xhr對象
    var xhr;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    };
    var data = oFile.files[0];
    //異步接受響應
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            if(xhr.status == 200){
                //實際操做
                result.innerHTML = xhr.responseText;
            }
        }
    }
    //發送請求
    xhr.open('post','pp.php',true);
    xhr.setRequestHeader("content-type",data.type);
    xhr.send(data);
}
</script>
複製代碼
複製代碼
<?php
$file = 'photo/test1.jpg';
touch($file);

function binary_to_file($file){
    $content = $GLOBALS['HTTP_RAW_POST_DATA'];  // 須要php.ini設置
    if(empty($content)){
        $content = file_get_contents('php://input'); //不須要php.ini設置,內存壓力小
    }
    $ret = file_put_contents($file, $content, true);
    return $ret;
};echo '文件上傳成功!';
?>
複製代碼

 

刪除文件

  最後,提一個小知識點,使用<input type="file>控件選擇文件後,如何刪除文件呢?通常地,有兩種方法。一種是使用form表單的reset()方法,重置表單;另外一種是將<input type="file>控件的value值置空,但第二種方法IE10-瀏覽器不支持

複製代碼
<form id="myForm">
  <input type="file" id="myFile">
</form>
<button id="btn1">刪除文件方法1</button>
<button id="btn2">刪除文件方法2</button>
<script>
var myFile = document.getElementById('myFile');
var myForm = document.getElementById('myForm');
btn1.onclick = function(){
  myFile.value = '';
}
btn2.onclick = function(){
  myForm.reset();
}
</script>
相關文章
相關標籤/搜索