HTML5中File對象初探

HTML5中File對象初探

2010
Jun
04
Tags: FileHTML5JavaScript
11條評論

在 HTML 5 中,JavaScript 得以獲得更多的權限來處理文件,而不再像這之前,只能獲得一個 file input 的 DOM。根據W3C的草案,JavaScript 被允許獲得文件的"文件名","大小","文件類型"等等信息,並允許通過一些不同形式的方法,獲得文件的內容,並將其通過 Ajax 傳送。事實上,已經有部分瀏覽器開始支持這一特性。但這並不意味着在這些瀏覽器中可以任意地訪問用戶的信息,JavaScript 只能通過被動的方式獲得文件,確切地說,就目前而言,可以通過 file input 和 用戶的拖放操作獲取到文件,這些信息,都被放在了 File 對象裏面。

Html5 File 初探

通過 Input 獲得 File 對象的方法:
<input type="file" id="input">
<!-- 如果你願意,可以在這個標籤裏寫上 "Multiple" 表示支持多文件形式 -->

接下來爲這個 input 元素添加 change 事件監聽。

	var inputElement = document.getElementById("input");  
	inputElement.addEventListener("change", handleFiles, false);
	
	function handleFiles(){
		var fileList = this.files;
		for( var i = 0 ; i < fileList.length ; i++ ){
			console.log(fileList[i]);
		}
	}

執行上面的代碼,將會在控制檯輸出 File 對象,多文件形式則輸出多個 File 對象。

正如代碼所呈現的那樣,通過監聽 input 元素,change 事件被觸發時,在監聽函數的 this 中,多出來一個"files"的屬性,關於 HTML 5 File 的玄妙就都在這裏面了。

通過拖拽操作獲得 File 對象的方法:
<div id="dropbox"> Drop Here </div>
var dropbox = document.getElementById("dropbox");  
dropbox.addEventListener("dragenter", dragenter, false);  
dropbox.addEventListener("dragover", dragover, false);  
dropbox.addEventListener("drop", drop, false); 

function dragenter(e) {  
    e.stopPropagation();  
    e.preventDefault();  
}  

function dragover(e) {  
    e.stopPropagation();  
    e.preventDefault();  
}

function drop(e) {  
    e.stopPropagation();  
    e.preventDefault();   
    var dt = e.dataTransfer;  
    var files = dt.files;
    //至此,已經達到了和上一種方式相同的目的
} 

顯而易見的,通過事件對象的 dataTransfer 可以得到文件,但同樣需要對它進行遍歷,因爲現在它還是一個 fileList 。 這就是 JavaScript 的被動獲取,只能通過監聽事件,當用戶有相應操作時,才能得到文件。這樣才能確保用戶的安全。

現在我們已經得到了 File 對象,接下來要考慮如何獲得文件的內容。在 W3C 草案中,File 對象只包含文件名,文件類型等只讀屬性。但 Firefox 已經爲其添加了幾個實用的方法,比如:

//讀取文件的二進制源碼
var fileBinary = file.getAsBinary();

但這並非 W3C 的標準的做法,根據其草案,有一個名爲 FileReader 的類(實爲對象)專門用以讀取文件內容,並且可以監控讀取狀態。

reader = new FileReader();

FileReader 提供的方法包括: "readAsBinaryString" ,"readAsDataURL" ,"readAsText" ,"abort" 等。下面的代碼就是一個使用 FileReader 將用戶選擇的圖片不通過後臺即時顯示出來的例子。

function handleFiles(files){
    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        var imageType = /image.*/;
        
        if (!file.type.match(imageType)) {
            continue;
        }
        
        var img = document.createElement("img");
        img.classList.add("obj");
        img.file = file;
        preview.appendChild(img);
        
        var reader = new FileReader();
        reader.onload = (function(aImg){
            return function(e){
                aImg.src = e.target.result;
            };
        })(img);
        reader.readAsDataURL(file);
    }
}

現在我們已經可以獲得文件對象,讀取文件的內容,最後要考慮的問題是如何同後端進行交互,即如何將讀取到的文件內容向後端發送。原理上是,通過 FileReader 的 readAsBinaryString 方法讀取到文件的二進制碼,然後通過 XMLHttpRequest 的 sendAsBinary 方法將其發送出去。

var xhr = new XMLHttpRequest();
xhr.open("POST", "url");
xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
// text/plain 爲你的文件類型,這可以通過 file 對象的 type 屬性獲取

xhr.sendAsBinary(binaryString);

這樣發出去的是二進制流,沒有表單域,沒有name,以php爲例,下面的示例代碼演示了後端如何接收數據,當然在實際開發中,還需要做更多。

//方法一
$content = $GLOBALS['HTTP_RAW_POST_DATA'];
file_put_contents('name.type',$content);
	
//方法二
$content = file_get_contents("php://input");
file_put_contents('name.type', $content);

資料:

HTML 5 仍處於草案階段。各瀏覽器支持程度不一,支持方式不一,資料匱乏,受衆面狹窄,項目開發仍需量力而行。 同時歡迎大家提出自己的看法和見解,對文中的錯誤進行指正。

PS. 本文示例代碼僅完全適用於 Firefox 3.6+ ,部分適用於其他支持 HTML 5 接口的瀏覽器,完全不適用於 IE8 及以下版本 。

發佈了19 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章