File、Blob、dataURL 和 canvas 的應用與轉換


File、Blob、dataURL 和 canvas 的應用與轉換

一、 概念介紹

1. File

(1) 通常情況下, File 對象是來自用戶在一個 <input> 元素上選擇文件后返回的 FileList 對象,也可以是來自由拖放操作生成的 DataTransfer 對象,或者來自 HTMLCanvasElement 上的 mozGetAsFile() API。

(2) File 對象基於 Blob,是特殊類型的 Blob,且可以用在任意的 Blob 類型的 context 中。比如:FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能處理 Blob 和 File。


2. Blob

(1) Blob 對象表示一個不可變、原始數據的類文件對象。它的數據可以按文本或二進制的格式進行讀取,也可以轉換成 ReadableStream 來用於數據操作。

(2) Blob 表示的不一定是 JavaScript 原生格式的數據。File 接口基於 Blob,繼承了 blob 的功能並將其擴展使其支持用戶系統上的文件。


3. dataURL

(1) Data URLs,即前綴為 data: 協議的 URL,其允許內容創建者向文檔中嵌入小文件。

(2) Data URLs 由四個部分組成:前綴(data:)、指示數據類型的 MIME 類型、如果非文本則為可選的 base64 標記、數據本身:data:[ ][;base64],


4. canvas

(1) Canvas API 提供了一個通過 JavaScript 和 HTML 的 <canvas> 元素來繪制圖形的方式。它可以用於動畫、游戲畫面、數據可視化、圖片編輯以及實時視頻處理等方面。


關系圖

二、相互轉化

1. File、Blob 轉化成 dataURL

FileReader 對象允許 Web 應用程序異步讀取文件(或原始數據緩沖區)內容,使用 File 或 Blob 對象指定要讀取的文件或數據。

function fileToDataURL(file) {
  let reader = new FileReader()
  reader.readAsDataURL(file)
  // reader 讀取文件成功的回調
  reader.onload = function (e) {
    return reader.result
  }
}

2. dataURL(base64) 轉化成 Blob(二進制)、File 對象

// dataURL 轉為 Blob
function dataURLToBlob(fileDataURL) {
  let arr = fileDataURL.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new Blob([u8arr], { type: mime })
}

// dataURL 轉為 File
function dataURLToBlob(fileDataURL, filename) {
  let arr = fileDataURL.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], filename, { type: mime })
}

3. File, Blob 文件數據繪制到 canvas

// 思路:File, Blob ——> dataURL ——> canvas

function fileAndBlobToCanvas(fileDataURL) {
  let img = new Image()
  img.src = fileDataURL
  let canvas = document.createElement('canvas')
  if (!canvas.getContext) {
    alert('瀏覽器不支持canvas')
    return
  }
  let ctx = canvas.getContext('2d')
  document.getElementById('container').appendChild(canvas)
  img.onload = function () {
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  }
}

4. 從 canvas 中獲取文件 dataURL

function canvasToDataURL() {
  let canvas = document.createElement('canvas')
  let canvasDataURL = canvas.toDataURL('image/png', 1.0)
  return canvasDataURL
}

三、完整栗子

可以點擊 這里 在線預覽

預覽圖

<!--
 * @Date: 2020-11-22 14:33:55
 * @information: datadURL File Blob canvas 的互相轉化
 *
 * File.prototype instanceof Blob === true
 * Blob.prototype instanceof Object === true
-->
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>datadURL File Blob canvas</title>
  <style>
    .body {
      text-align: center;
    }
    .img-box {
      margin: 20px 0;
    }
    #img {
      width: 60%;
    }
  </style>
</head>
<body>

  <div class="body">

    <div class="input-box">
      <input id="input" type="file" accept="image/png, image/jpeg" onchange="onChangeInput()">
    </div>

    <div class="img-box">
      img:
      <img src="" alt="img" id="img">
    </div>

    <div class="canvas-box" id="canvas-box">
      canvas:
    </div>

  </div>


<script>
  // 文件對象
  let file;
  // 文件 base64 碼
  let fileDataURL;


  /**
   * @Date: 2020-11-25 10:32:51
   * @information: 獲取文件
   */
  function onChangeInput() {
    file = document.getElementById('input').files[0]
    console.log('file->', file)
    if(!FileReader) {
      alert('瀏覽器版本過低,請升級版本')
      return;
    }
    fileToDataURL()
  }

  /**
   * @Date: 2020-11-25 10:31:47
   * @information: 使用 FileReader 讀取文件內容, File(二進制) ——> dataURL(base64)   Blob ——> dataURL 同理
   */
  function fileToDataURL() {
    let reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = function(e) {
      console.log('dataURL->', reader.result)
      fileDataURL = reader.result
      showImg()
      dataURLToBlob()
    }
  }

  /**
   * @Date: 2020-11-25 10:33:13
   * @information: 圖片回顯
   */
  function showImg() {
    let img = document.getElementById('img')
    img.src = fileDataURL
  }

  /**
   * @Date: 2020-11-25 10:34:47
   * @information: dataURL(base64) ——> Blob(二進制)對象
   */
  function dataURLToBlob() {
    let arr = fileDataURL.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while(n --) {
      u8arr[n] = bstr.charCodeAt(n)
    }
    console.log('blob->', new Blob([u8arr], {type: mime}))
    fileAndBlobToCanvas()
    return new Blob([u8arr], {type: mime})
  }

  /**
   * @Date: 2020-11-25 10:53:31
   * @information: File, Blob 文件數據繪制到 canvas
   * 思路:File, Blob ——> dataURL ——> canvas
   */
  function fileAndBlobToCanvas() {
    let img = new Image()
    img.src = fileDataURL
    let canvas = document.createElement('canvas')
    if(!canvas.getContext) {
      alert('瀏覽器不支持canvas')
      return;
    }
    let ctx = canvas.getContext('2d')
    document.getElementById('canvas-box').appendChild(canvas)
    img.onload = function() {
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
      canvasToDataURL()
    }
  }

  /**
   * @Date: 2020-11-25 11:23:54
   * @information: 從 canvas 中獲取文件 dataURL
   */
  function canvasToDataURL() {
    let canvas = document.createElement('canvas')
    let canvasDataURL = canvas.toDataURL('image/png', 1.0)
    console.log('從 canvas 中獲取文件 dataURL :', canvasDataURL)
  }

</script>

</body>
</html>






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM