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

上傳咱們通常都是用「input[type=file]」控件。當你用此控件時,你就受權了網頁和服務器訪問對應的文件,就能夠獲得File對象。javascript

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

下面的示例代碼能夠在這裏查看到。html5

1、accept屬性

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

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

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

 

2、change事件

通常選擇文件都會使用「change」事件,下面的代碼就是綁定了change事件,彈出文件大小:web

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

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

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

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

使用「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);

 

3、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對象中的方法來取代。

 

4、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)內容以下:

 

5、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;

 

6、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);
}

 

7、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);

 

 

參考資料:

https://developer.mozilla.org/zh-CN/docs/Using_files_from_web_applications    在web應用中使用文件

http://javascript.ruanyifeng.com/htmlapi/file.html    文件和二進制數據的操做

http://www.iunbug.com/archives/2012/06/04/208.html   [譯]JavaScript文件操做基礎

http://www.iunbug.com/archives/2012/06/05/254.html   [譯]JavaScript文件操做URL對象

http://www.html5rocks.com/zh/tutorials/file/dndfiles/     經過 File API 使用 JavaScript 讀取文件

相關文章
相關標籤/搜索