不通過 <input type='file' />上傳文件圖片到服務(wù)器

在瀏覽器中操作文件,多數(shù)情況下用到的是 File 對象,從 <input type='file' /> 元素獲取,進而繼續(xù)操作(例如將選擇的圖片展示在頁面上,用ajax將文件上傳至服務(wù)器等)。這里介紹在HTTP獲取圖片URL創(chuàng)建圖片,canvas拼接文字,上傳到服務(wù)器。

一、canvas獲取dataURL

/**
 * 根據(jù)二維碼畫canvas合成文字
 * @param {string} src  二維碼圖片路徑
 * @param {string} text  拼接的二維碼文字
 * @return {string} src 合成后的圖片地址
 */
export async function drawImage(src, text) {
  const img = await createImg(src);
  const canvas = document.createElement('canvas');
  let context = canvas.getContext('2d');
  // 確保canvas的尺寸和圖片一樣
  const width = img.width;
  const height = img.height;
  canvas.width = img.width;
  canvas.height = img.height + 50;
  context.drawImage(img, 0, 0, width, height);
  context.fillStyle = '#FFF';
  context.fillRect(0, img.height, width, 50);
  const font = '20px Arial bolder';
  context.font = font;
  context.fillStyle = 'black';
  context.fillText(text, width / 2 - (context.measureText(font).width / 2), img.height + 29);
  let url = canvas.toDataURL();
  // canvas 轉(zhuǎn)為blob類型 可直接傳入file
  // canvas.toBlob((blob) => {
  //   console.log(blob);
  //   var myFile = new File([blob], 'aa.png', {
  //     type: 'mime'
  //   });
  // });
  return url;
}
/**
 * 創(chuàng)建圖片
 * @param {string} src 被創(chuàng)建圖片的src或者base64
 * @return {Promise.<resolveType, rejectType>}
 */
function createImg(src) {
  return new Promise((resolve, reject) => {
    let image = new Image();
    image.crossOrigin = 'anonymous';
    image.onload = () => {
      resolve(image);
    };
    image.onerror = () => {
      reject({
        errStr: '圖片加載失敗,請重試'
      });
      console.log('圖片加載失敗,請重試');
    };
    image.src = src;
  });
}

二、二進制數(shù)據(jù)容器

  • blob:適用于讀取二進制數(shù)據(jù),比如圖片文件

    • 表示不可變、原始數(shù)據(jù)的類文件對象(js都不一定認得)
    • blob更偏重于整體操作(整個文件的二進制流)
  • ECMAScript二進制數(shù)組 按照數(shù)組的方式處理二進制數(shù)據(jù)

    • js可以識別的二進制數(shù)據(jù)
  • 可以做流的切割,所有注重于對二進制流中的字節(jié)進行處理

1. 第一種方式

我第一次采取的方法利用canvas的todataurl方法獲取dataurl后 :拿到dataurl后獲取逗號后面的編碼數(shù)據(jù)利用window.atob將編碼解碼,將解碼后的字符串使用charcodeat獲取每一個字符串的unicode字符,然后存入Uint8Array數(shù)組,創(chuàng)建文件對象,放入form表單中上傳到服務(wù)器。

dataURL是base64編碼的數(shù)據(jù)格式
(將 dataURL 轉(zhuǎn)為 blob對象:網(wǎng)上有用new Blob([u8arr], { type: mime }); 把Uint8Array轉(zhuǎn)為blob,再后續(xù)操作也可以,我給省去了)

/**
 * 將base64轉(zhuǎn)換為文件
 * @param {string} apiUrl 服務(wù)器地址
 * @param {string} dataurl url
 * @param {string} imageName 圖片名字
 * @return {Object} response 文件信息
 */
export function dataURLtoFile(apiUrl, dataurl, imageName) {
  // 將base64轉(zhuǎn)換為文件流
  const arr = dataurl.split(',');
  // 獲取逗號后面的編碼數(shù)據(jù)利用window.atob將編碼解碼
  const mime = arr[0].match(/:(.*?);/)[1];
  const bstr = atob(arr[1]);
  // 解碼后的字符串使用charcodeat獲取每一個字符串的unicode字符
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  // 存入Uint8Array數(shù)組 創(chuàng)建文件對象
  var myFile = new File([u8arr], imageName, {
    type: mime
  });
  var formData = new FormData();
  // 將文件轉(zhuǎn)二進制
  formData.append('file', myFile);
  let config = {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  };
  // 通過axios將圖片上傳至服務(wù)器
  return new Promise((resolve, reject) => {
    axios.post(apiUrl, formData, config).then(res => {
      const response = res.data;
      if (response && response.errNo === 0) {
        const {
          data
        } = response;
        resolve(data);
      }
      else {
        reject(response.errstr);
      }
    })
      .catch(err => {
        reject(err);
        console.log(err);
      });
  });
}
  1. 第二種方法

后整理時發(fā)現(xiàn)file對象要求傳入的文件內(nèi)容也可以是Blob,想到canvas也可以轉(zhuǎn)為blob對象

image

于是就測試了canvas不用toDataURL(),用toBlob()直接把blob傳入new file()中,這樣代碼簡略了很多

var blob = canvas.toBlob((blob) => {
    console.log(blob);
    var myFile = new File([blob], 'aa.png', {
      type: 'mime'
    });
    console.log(myFile);
  });

對比結(jié)果

-第一種方式的file對象

image.png

-第二種的blob 和file對象

image

這是測試上傳到我本地自建的服務(wù)器中,是一樣的,size少了1 ,忽略掉圖片名字和后綴,測試寫死了, 正常都應(yīng)是動態(tài)傳進來的

image

再提供幾個常用的轉(zhuǎn)換參考

blob轉(zhuǎn)dataUrl:

用途:拿到blob對象后,希望展示這個數(shù)據(jù)

用法:使用window.URL.createObjectURL(blob)拿到dataUrl對象,然后進行展示

canvan轉(zhuǎn)blob:canvas 最新的方法 toblob

canvas轉(zhuǎn)dataurl:canvas的實例方法 todataurl

blob轉(zhuǎn)canvas:blob轉(zhuǎn)換為dataurl對象后 新疆一個圖片用來顯示dataurl數(shù)據(jù),然后將圖片放入canvas中

dataurl轉(zhuǎn)canvas:dataurl先變成圖片再放入canvas

img轉(zhuǎn)canvas:canvas的drawImage方法支持將img放入canvas

canvas轉(zhuǎn)img:利用canvas的todataurl方法獲取圖片數(shù)據(jù)后,新建圖片控件展示圖片

萌新記錄 歡迎大佬指點
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容