移動端圖片操作(一)——上傳

傳我們一般都是用“input[type=file]”控件。當你用此控件時,你就授權了網頁和服務器訪問對應的文件,就可以得到File對象。

友情提示在,在Android手機webview中,是不支持上傳文件的,網上說是修改Android端的代碼,但我沒試過,我們這邊是使用客戶端提供的接口來實現上傳的。

下面的示例代碼可以在這裏查看到。

一、accept屬性

該屬性表明了服務器端可接受的文件類型,可以限制你手機選擇相關的文件,如果限制多個,可以用逗號分割,下面的代碼就表示只能選擇圖片與音頻相關的文件:

<input accept="image/*,audio/*" type="file"/>

在移動端,點擊後會讓你選擇拍照或相冊,還是蠻高大上的。下圖是UC瀏覽器中:

 

二、change事件

一般選擇文件都會使用“change”事件,下面的代碼就是綁定了change事件,彈出文件大小:

var upload = document.getElementById('upload');
upload.addEventListener('change', function() {
  var file = upload.files[0];
  alert(file.size);
}, false);

1) 有些手機瀏覽器在點擊的時候,會彈出鍵盤選擇,我用οnfοcus="this.blur()",來強制失去焦點。

<input type="file" id="upload" onfocus="this.blur()"/>

2) 當選擇過一次後,再次選擇同一個文件,“change”事件不會觸發,因爲value沒有改變,在網上看到個方法,我還沒有在實際項目中使用,兼容性有待考證。

使用“Node.cloneNode”複製上傳元素,再用“Node.replaceChild”替換節點。

這裏注意下:克隆一個元素節點會拷貝它所有的屬性以及屬性值,但不會拷貝那些使用addEventListener()方法或者node.onclick = fn用JavaScript動態綁定的事件。

upload.addEventListener('change', function() {
  var upload = document.getElementById('upload'); //每次要動態獲取
  var file = upload.files[0];
  console.log(file.size);

  //解決上傳相同文件不觸發onchange事件  
  var clone = upload.cloneNode(true);
  clone.onchange = arguments.callee; //克隆不會複製動態綁定事件
  clone.value = '';
  upload.parentNode.replaceChild(clone, upload);
}, false);

 

三、File對象

用戶所選擇的文件都存儲在了一個FileList對象上,其中每個文件都對應了一個File對象

File對象負責處理那些以文件形式存在的二進制數據,也就是操作本地文件。

File對象是Blob【下面會提到】的特殊類型,即大塊的二進制數據,File對象的尺寸及類型等屬性都繼承自Blob。

1)File對象可以通過3種方式獲取:

1. <input>元素上選擇文件後返回的FileList對象中的成員

2. 拖放操作【Drag或Drop】生成的 DataTransfer對象內files屬性中的成員

3. HTMLCanvasElement上執行mozGetAsFile()方法後的返回結果

document.getElementById('upload').files[0]//選取第一個文件對象

2)File對象有9個屬性,這裏就只介紹3個:

1. name:當前File對象所引用文件的文件名,不包括路徑,只讀。

2. size:文件大小,單位爲字節,只讀的64位整數.

3. type:MIME類型,只讀字符串,如果類型未知,則返回null。有些移動端的瀏覽器明明選擇了圖片,返回的卻是null,非常坑。

還有3個非標準的方法:getAsBinary()、getAsDataURL()和getAsText(in DOMString encoding)。

這3個方法現在已經過時,現在用FileReader對象中的方法來取代。

 

四、FileReader

web應用程序可以異步的讀取存儲在用戶計算機上的文件(或者原始數據緩衝)內容,可以使用File對象或者Blob對象來指定所要處理的文件或數據。

1) readAsArrayBuffer():在返回的result屬性中將包含一個ArrayBuffer對象【緩衝數組,是一種用於呈現通用、固定長度的二進制數據的類型】以表示所讀取文件的內容

Blob可以“append”,ArrayBuffer數據。ArrayBuffer存在的意義就是作爲數據源提前寫入在內存中,就是提前釘死在某個區域,長度也固定。

2) readAsBinaryString():result屬性中將包含所讀取文件的原始二進制數據

3) readAsDataURL():result屬性中將包含一個data: URL格式的字符串以表示所讀取文件的內容

4) readAsText():result屬性中將包含一個字符串以表示所讀取的文件內容

下面的代碼是獲取data:URL,可以將返回的result內容賦值給img的src,用於預覽等操作。

var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
  var img = new Image();
  img.src = this.result;
  console.log(this.result);
};
console.log(this.result)內容如下:

 

五、URL對象

URL對象是硬盤上指向文件的URL。上面的例子中獲取圖片的引用,通過讀取data URI,data URI是個一大串的字符。

圖片原本就在硬盤上,還要轉換成另一個格式再用,有點繞了,完全可以直接引用文件的URL,下面是兩個方法:

1) URL.createObjectURL():接收一個文件的引用(File或Blob對象)返回一個URL對象

2) URL.revokeObjectURL():銷燬創建的URL

var url = URL.createObjectURL(file);
var img = new Image();
img.src = url;
img.onload = function(e) {
  window.URL.revokeObjectURL(this.src); //銷燬
}
console.log(url);

console.log(url)內容如下:

在移動端需要做個兼容性判斷:

window.URL = window.URL || window.webkitURL;

 

六、Blob對象

Blob(binary large object)對象代表了一段二進制數據,就是一個包含只讀原始數據的類文件對象。

File接口基於Blob,繼承了Blob的功能,並且擴展支持了用戶計算機上的本地文件。

1)創建Blob對象的4種方法:

1. 調用Blob構造函數

2. 使用一個已有Blob對象上的slice()方法切出另一個Blob對象

3. 調用canvas對象上的toBlob方法

4. 過氣的方法,通過BlobBuilder接口創建,但兼容性不好,並且現有的BlobBuilder實現都是帶前綴的

 

2)利用Blob對象,生成可下載文件

var blob = new Blob(["pwstrick"]);//數組中添加DOMString對象
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);//創建URL對象
a.download = "test.txt";//HTML5新屬性
a.textContent = "test";            
document.getElementsByTagName('body')[0].appendChild(a);

生成一個“a”標籤,並且點擊這個鏈接,可以下載一個txt文本,內容是“pwstrick”。

 

3)通過slice方法,將二進制數據按照字節分塊,返回一個新的Blob對象

upload.addEventListener('change', function() {
  var upload = document.getElementById('upload'); //每次要動態獲取
  var file = upload.files[0];
  var start = 0;
  var chunk = 1024 * 10; //10KB
  var end = start + chunk;
  var size = file.size;
  while (start < size) {
    segment(file, start, end);
    start = end;
    end = start + chunk;
    if (end > size) {
      end = size;
    }
  }
}, false);

function segment(file, start, end) {
  var reader = new FileReader();
  reader.onload = function(evt) {
    console.log(['Read bytes: ', start, ' - ', end].join(''));
  };
  var blob = file.slice(start, end);
  reader.readAsBinaryString(blob);
}

 

七、formData

XMLHttpRequest Level 2添加了一個新的接口FormData

利用FormData對象,可以使用鍵值對來模擬一個完整的表單,然後使用XMLHttpRequest發送這個"表單"。

使用FormData的最大優點就是我們可以異步上傳一個二進制文件。

  var formData = new FormData();
  formData.append("name", "value");//普通鍵值對
  formData.append("blob", blob); //傳遞一個blob對象
  formData.append("file", file); //傳遞一個file對象
  var oReq = new XMLHttpRequest();
  oReq.open("POST", "http://xx.com");

oReq.send(formData);

轉自:http://www.cnblogs.com/strick/p/5181701.html

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