成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

「HTML5」FileAPI 文件操作實(shí)戰(zhàn)

Jacendfeng / 1593人閱讀

摘要:準(zhǔn)備工作首先,我們的來自于標(biāo)簽中選中的文件列表。用戶選中的文件信息也會(huì)傳入回調(diào)函數(shù)的第一個(gè)參數(shù)中。唯一需要特殊處理的是文件對(duì)象的獲取入口改變了。對(duì)于標(biāo)簽,監(jiān)聽事件,存放在中對(duì)于拖拽操作,存放在拖拽事件的回調(diào)函數(shù)參數(shù)里,通過訪問即可。

本文來自《FileAPI 文件操作實(shí)戰(zhàn)》

其他所有系列都放在了Github。歡迎交流和Star。

介紹

HTML5 為我們提供了 File API 相關(guān)規(guī)范。主要涉及 File 接口 和 FileReader 對(duì)象 。

本文整理了兼容性檢測(cè)、文件選擇、屬性讀取、文件讀取、進(jìn)度監(jiān)控、大文件分片上傳以及拖拽上傳等開發(fā)中常見的前端文件操作。

準(zhǔn)備工作

首先,我們的 File 來自于標(biāo)簽中選中的文件列表。所以,準(zhǔn)備如下的 HTML 代碼:


檢測(cè)兼容性

File 對(duì)象是特殊類型的 Blob。在 script 入口處,應(yīng)該檢測(cè)當(dāng)前瀏覽器是否支持 File API:

if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
  throw new Error("當(dāng)前瀏覽器對(duì)FileAPI的支持不完善");
}
監(jiān)聽文件選擇

對(duì)于 type 為 file 類型的標(biāo)簽,在選擇文件的時(shí)候,會(huì)觸發(fā)change事件。用戶選中的文件信息也會(huì)傳入回調(diào)函數(shù)的第一個(gè)參數(shù)中。

function handleFileSelect(event) {
  const { files } = event.target;
  if (!files.length) {
    console.log("沒有選擇文件");
    return;
  }

  console.log("選中的文件信息是:", files);
}

document
  .querySelector("#files")
  .addEventListener("change", handleFileSelect, false);
文件屬性-File

event.target.files 是一個(gè)FileList對(duì)象,它是一個(gè)由File對(duì)象組成的列表。

每個(gè) File 對(duì)象,保存著選中的對(duì)應(yīng)文件的屬性。常用的用:

name:文件名

type:文件類型

size:文件大小

下面,通過 type 屬性,過濾掉非圖片類型的文件,只展示圖片類型文件的信息:

function handleFileSelect(event) {
  const { files } = event.target;
  if (!files.length) {
    console.log("沒有選擇文件");
    return;
  }

  const innerHTML = [];
  const reImage = /image.*/;

  for (let file of files) {
    if (!reImage.test(file.type)) {
      continue;
    }

    innerHTML.push(
      `
      
  • ${file.name} (${file.type || "n/a"}) - ${file.size} bytes
  • ` ); } document.querySelector("#list").innerHTML = `
      ${innerHTML.join("")}
    `; }
    讀取文件-FileReader

    還是以圖片讀取為例,讀取并且顯示所有的圖片類型文件。

    文件讀取需要使用FileReader對(duì)象,它常用 3 個(gè)回調(diào)方法:

    onload: 文件讀取完成

    onloadstart:文件上傳開始

    onprogress : 文件上傳中觸發(fā)

    Image類似,在讀取文件之前,需要先綁定事件處理。它讀取操作有:readAsArrayBuffer、readAsDataURL、readAsBinaryString、readAsText。傳入的參數(shù)就是File對(duì)象。

    那么這幾個(gè)方法有什么區(qū)別呢?不同的讀取方式,回調(diào)事件onload接受到的event.target.result不相同。比如,readAsDataURL讀取的話,result 是一個(gè)圖片的 url。

    下面就是讀取圖片文件,然后展示的一個(gè)例子:

    function handleFileSelect(event) {
      let { files } = event.target;
      if (!files.length) {
        return;
      }
    
      let vm = document.createDocumentFragment(),
        re = /image.*/,
        loaded = 0, // 完成加載的圖片數(shù)量
        total = 0; // 總共圖片數(shù)量
    
      // 統(tǒng)計(jì)image文件數(shù)量
      for (let file of files) {
        re.test(file.type) && total++;
      }
    
      // onloadstart回調(diào)
      const handleLoadStart = (ev, file) =>
        console.log(`>>> Start load ${file.name}`);
      // onload回調(diào)
      const handleOnload = (ev, file) => {
        console.log(`<<< End load ${file.name}`);
    
        const img = document.createElement("img");
        img.height = 250;
        img.width = 250;
        img.src = ev.target.result;
        vm.appendChild(img);
    
        // 完成加載后,將其放入dom元素中
        if (++loaded === total) {
          document.querySelector("#images").appendChild(vm);
        }
      };
    
      for (let file of files) {
        if (!re.test(file.type)) {
          continue;
        }
    
        const reader = new FileReader();
        reader.onloadstart = ev => handleLoadStart(ev, file);
        reader.onload = ev => handleOnload(ev, file);
        // 讀取文件對(duì)象
        reader.readAsDataURL(file);
      }
    }
    
    document
      .querySelector("#files")
      .addEventListener("change", handleFileSelect, false);
    監(jiān)控讀取進(jìn)度

    在監(jiān)控讀取進(jìn)度的時(shí)候,主要是處理 FileReader 對(duì)象上的 onprogress 事件。

    下面的例子,請(qǐng)打開一個(gè)較大的文件來查看效果(否則一下就讀取完了):

    function handleFileSelect(event) {
      let { files } = event.target;
      if (!files.length) {
        return;
      }
    
      const handleLoadStart = (ev, file) =>
        console.log(`>>> Start load ${file.name}`);
      const handleProgress = (ev, file) => {
        if (!ev.lengthComputable) {
          return;
        }
        // 計(jì)算進(jìn)度,并且以百分比形式展示
        const percent = Math.round((ev.loaded / ev.total) * 100);
        console.log(`<<< Loding ${file.name}, progress is ${percent}%`);
      };
    
      for (let file of files) {
        const reader = new FileReader();
        reader.onloadstart = ev => handleLoadStart(ev, file);
        reader.onprogress = ev => handleProgress(ev, file);
        reader.readAsArrayBuffer(file);
      }
    }
    
    document
      .querySelector("#files")
      .addEventListener("change", handleFileSelect, false);
    大文件分片讀取

    在對(duì)于超大文件,一般采用分片上傳的思路解決。文章開頭有講到,F(xiàn)ile 是 Blob 的一個(gè)特例。而 Blob 上有一個(gè)slice 方法,通過它,前端就可以實(shí)現(xiàn)分片讀取大文件的操作。

    為了方便說明,請(qǐng)先準(zhǔn)備好一個(gè) txt 文件,文件內(nèi)容就是:hello world。

    示例代碼如下,代碼中只讀取前 5 個(gè)字節(jié),由于每個(gè)英文字母占 1 個(gè)字節(jié),所以打印結(jié)果應(yīng)該是“hello”。

    function handleFileSelect(event) {
      let { files } = event.target;
      if (!files.length) {
        return;
      }
      // 為了方便說明,這里僅僅讀取第一個(gè)文件
      const file = files[0];
      // 讀取前5個(gè)字節(jié)的內(nèi)容
      const blob = file.slice(0, 5);
    
      const reader = new FileReader();
      // 控制臺(tái)輸出結(jié)果應(yīng)該是:hello
      reader.onload = ev => console.log(ev.target.result);
      reader.readAsText(blob);
    }
    
    document
      .querySelector("#files")
      .addEventListener("change", handleFileSelect, false);
    拖拽上傳

    和前面所述的 File API 相關(guān)是完全一樣的。唯一需要特殊處理的是文件對(duì)象的獲取入口改變了。對(duì)于標(biāo)簽,監(jiān)聽 onchange 事件,F(xiàn)ileList 存放在 event.target.files 中;對(duì)于拖拽操作,F(xiàn)ileList 存放在拖拽事件的回調(diào)函數(shù)參數(shù)里,通過 event.dataTransfer.files 訪問即可。

    需要修改一下 html 代碼:

    
    
      
      
    
    
      

    腳本文件的代碼如下:

    function handleDropover(event) {
      event.stopPropagation();
      event.preventDefault();
    }
    
    function handleDrop(event) {
      event.stopPropagation();
      event.preventDefault();
      /***** 訪問拖拽文件 *****/
      const files = event.dataTransfer.files;
      console.log(files);
      /**********/
    }
    
    const target = document.querySelector("#container");
    target.addEventListener("dragover", handleDropover);
    target.addEventListener("drop", handleDrop);
    后端相關(guān)

    后端相關(guān)超出了本文的討論范圍,可以參考這篇文章。

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105889.html

    相關(guān)文章

    • 瀏覽器端下載那些事

      摘要:三瀏覽器方式相信大家對(duì)這個(gè)對(duì)象也不太陌生,它是標(biāo)準(zhǔn)里的一個(gè)二進(jìn)制數(shù)據(jù)對(duì)象,可以與對(duì)象配合,進(jìn)行文件的下載。其實(shí)這樣一個(gè)簡(jiǎn)單的,就可以實(shí)現(xiàn)瀏覽器端自己的下載了。 一、背景 最近寫了一個(gè)react的組件,用來做文件導(dǎo)出。環(huán)境是ie10+。細(xì)一點(diǎn)說,就是 1、讀取form里的數(shù)據(jù) 2、向服務(wù)端發(fā)請(qǐng)求,并下載文件;要求拿到請(qǐng)求狀態(tài),如果出錯(cuò)及時(shí)反饋給用戶。 第一個(gè)需求,我們借用了jquer...

      3fuyu 評(píng)論0 收藏0
    • [練習(xí)]JS鼠標(biāo)拖拽(DnD)操作

      拖放(Drag and Drop,DnD)操作因?yàn)樯婕暗脚c底層OS的結(jié)合,所以是較為復(fù)雜的交互操作。 這里先實(shí)現(xiàn)一個(gè)簡(jiǎn)單的拖拽圖片到瀏覽器顯示到操作, 主要用到了HTML5中的FileAPI: 先上DEMODnD demo 需要注意的是瀏覽器通過取消相應(yīng)的拖拽事件來表明它對(duì)該事件有興趣, 比如通過取消dragover來表明瀏覽器已經(jīng)做好準(zhǔn)備接受進(jìn)一步的拖拽,接著說dragend最后到drop,dr...

      jsummer 評(píng)論0 收藏0
    • Vue2.0利用vue-resource上傳文件到七牛

      摘要:年底,公司項(xiàng)目番茄表單的前端部分,開始了從傳統(tǒng)的到的徹底重構(gòu)。上傳流程圖不重要看文字事件觸發(fā)后,先去如果是圖片,可以同時(shí)通過以及將圖片預(yù)覽在頁面上后臺(tái)請(qǐng)求七牛的上傳,將拿到的和以及通過傳遞過來的一起到中。 關(guān)于上傳,總是有很多可以說道的。16年底,公司項(xiàng)目番茄表單的前端部分,開始了從傳統(tǒng)的jquery到vue 2.0的徹底重構(gòu)。但是上傳部分,無論是之前的傳統(tǒng)版本,還是Vue新版本,都是...

      lcodecorex 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <