Some common methods of front-end file conversion processing

This article focuses on the processing of image files, such as converting url to file, converting to base64; converting file to blob type, etc.

注意: Do not convert the video file to base64, because the base64 format is essentially a long string of characters. If a larger video file is uploaded on the mobile phone, it will cause the page to automatically refresh, the program to crash, or even the browser to 转bsee64的操作directly Killed by the system, because the base64 string of the video is too large to support the memory.

If you want to echo the video after uploading the video file, you can use createObjectUrl()the method to generate a temporary memory address to access.


0, Preface

JavaScript provides some APIs to handle files or raw file data, such as: File, Blob, FileReader, ArrayBuffer, base64, etc.; knowing them will make it easier to understand some of the methods below;

Recommend reading the following blogs

(知乎):1,https://zhuanlan.zhihu.com/p/568915443
(csdn):2,https://blog.csdn.net/mrlaochen/article/details/120209650

insert image description here



1. Convert the url network link (http://) of the picture to base64 format

/**
 * 将图片的url网络链接(http://) 转为base64格式
 * @param {string}
 */
 export function imgUrlToBase64(imgUrl) {
    
    
  return new Promise((resolve) => {
    
    
    var img = new Image();
    img.src = imgUrl;
    // 设置图片跨域属性
    img.setAttribute("crossOrigin", "anonymous");
    // 注意 onload是异步的行为
    img.onload = () => {
    
    
      var canvas = document.createElement("canvas");
      canvas.width = img.width;
      canvas.height = img.height;
      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0);
      var dataURL = canvas.toDataURL("image/png");
      resolve(dataURL);
    };
  });
}

Use as follows:

      // 网络图片链接
      let finalImg = "https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&fmt=auto&app=120&f=JPEG?w=1140&h=641";
      // 开始使用
      imgUrlToBase64(finalImg).then((res) => {
    
    
          console.log("res:", res);
      });

2. Convert the base64 image data to a file file

/**
 * 将以base64的图片数据转换为File文件
 * @param {string}
 */
export function base64ToFile(dataUrl, fileName = "myFile") {
    
    
  let arr = dataUrl.split(",");
  let mime = arr[0].match(/:(.*?);/)[1];
  let suffix = mime.split("/")[1];
  let bstr = atob(arr[1]);
  let n = bstr.length;
  let u8arr = new Uint8Array(n);
  while (n--) {
    
    
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], `${
      
      fileName}.${
      
      suffix}`, {
    
    
    type: mime
  });
}

Use case :

      <input type="file" />
      // 原生添加点击事件
      document.getElementsByTagName("input")[0].onchange = async function (e) {
    
    
        // 拿到的文件类型
        let file = e.target.files[0];
        console.log("file:",file);
        // 先转为base64
        let base64 = await fileTransferBase64(file);
        
        // 将以base64的图片url数据转换为File文件
        let file2 = base64ToFile(base64)  ================注意看这行===================
        console.log("file2:", file2);
      };

3. Convert the image data in base64 to Blob

/**
 * 将以base64的图片数据转换为Blob 
 * @param urlData 用url方式表示的base64图片数据
 */
      function base64UrlToBlob(urlData, filename) {
    
    
        try {
    
    
          if (urlData == "" || !urlData) {
    
    
            return console.warn("urlData不存在");
          }
          if (!filename) {
    
    
            filename = "myfile";
          }
          // 以base64的图片url数据转换为Blob
          var arr = urlData.split(","),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
          while (n--) {
    
    
            u8arr[n] = bstr.charCodeAt(n);
          }
          let bold = new Blob([u8arr], {
    
     type: mime });
          return {
    
     bold, filename };
        } catch (error) {
    
    
          console.warn("base64转换为Blob出问题了:", error);
        }
      }

Use case :

 	  <input type="file" />
 	  
      // 原生添加点击事件
      document.getElementsByTagName("input")[0].onchange = async function (e) {
    
    
        // 拿到的文件类型
        let file = e.target.files[0];
        console.log("file:", file);
        let base64 = await fileTransferBase64(file);

        // 将以base64的图片url数据转换为File文件
        let blob = base64UrlToBlob(base64);  =======注意这行=========
        console.log("blob:", blob);
      };

4. Convert file to base64

  /**
   * 将file文件转化为base64 使用promise
   * @param file 该文件的file类型
   */
  export function fileTransferBase64(file) {
    
    
    try {
    
    
      return new Promise((resolve, reject) => {
    
    
        const reader = new FileReader(); //异步读取
        reader.readAsDataURL(file);
        // 成功和失败返回对应的信息,reader.result一个base64,可以直接使用
        reader.onload = (e) => {
    
    
          resolve(e.target.result);
        };
        // 失败返回失败的信息
        reader.onerror = (error) => {
    
    
          console.warn('file文件转化为base64s失败:', error);
          reject(error);
        };
      });
    } catch (error) {
    
    
      console.warn('捕获fileTransferBase64方法的错误:', error);
    }
  }

Use case :

The transfer file type involves asynchrony, so use it promiseto encapsulate it;

      <input type="file" />
  
      // 原生添加点击事件
      document.getElementsByTagName("input")[0].onchange = async function (e) {
    
    
        // 拿到的文件类型
        let file = e.target.files[0];
        // 转file类型 涉及到异步 所以要用 promise
        let base64 = await fileTransferBase64(file)
        console.log("base64:",base64);
      };
  

5. Convert file to Blob

  /**
   * 直接将file数据转换为Blob 
   * @param file格式
   */
  export function fileToBlob(file) {
    
    
    return new Promise((resolve, reject) => {
    
    
      // FileReader  异步读取文件
      const reader = new FileReader();
      // readAsDataURL: dataurl它的本质就是图片的二进制数据, 进行base64加密后形成的一个字符串,
      reader.readAsDataURL(file);
      // 成功和失败返回对应的信息,reader.result一个base64,可以直接使用
      reader.onload = (e) => {
    
    
        let arr = e.target.result.split(',');
        let mime = arr[0].match(/:(.*?);/)[1];
        console.log(mime);
        const blob = new Blob([e.target.result], {
    
     type: mime });
        resolve(blob);
      };
      // 失败返回失败的信息
      reader.onerror = (error) => {
    
    
        console.warn('file数据转换为Blob失败:', error);
        reject(error);
      };
    });
  }

Use case :

Converting blob type also involves asynchrony, so use promiseto encapsulate it;

      <input type="file" />
      
      // 原生添加点击事件
      document.getElementsByTagName("input")[0].onchange = async function (e) {
    
    
        // 拿到的文件类型
        let file = e.target.files[0];
        // 转file类型 涉及到异步 所以要用 promise
        let blob = await fileToBlob(file);
        console.log("blob:", blob);
      };

6. The local memory address of the obtained file (picture video, etc.) can be directly accessed

This method can be used to echo after uploading a file.

  /**
   * 获取文件(图片视频等)的本地内存地址 可以直接访问
   * @param file  该文件的文件流
   */
  export function createObjectURLFun(file) {
    
    
    let url = '';
    if (window.createObjectURL != undefined) {
    
    
      // basic
      url = window.createObjectURL(file);
    } else if (window.URL != undefined) {
    
    
      // mozilla(firefox)
      url = window.URL.createObjectURL(file);
    } else if (window.webkitURL != undefined) {
    
    
      // webkit or chrome
      url = window.webkitURL.createObjectURL(file);
    }
    return url;
  }

Use case :

      // 原生添加点击事件
      document.getElementsByTagName("input")[0].onchange = async function (e) {
    
    
        // 拿到的文件类型
        let file = e.target.files[0];
        let objectURL = createObjectURLFun(file)
        console.log("objectURL:", objectURL); 
        //打印结果:  objectURL: blob:null/31fff142-4b83-4749-b71d-a9a4f6c16a43
      };

7. Video frame capture (capture the first frame of the video)

The first frame of the video file is often intercepted after uploading the video file and used as the cover;

The first:

/**
 * 获取视频的第一帧 来当做封面  
 * @param url 视频的url 可以是一个由window.URL.createObjectURL返回的视频内存临时地址(推荐使用)
 */
export function getFirstImg(url) {
    
    
  return new Promise(function (resolve, reject) {
    
    
    try {
    
    
      let dataURL = '';
      let width = '90'; // 单位是px 可以随意更改
      let height = '90';
      let listen = 'canplay';//需要监听的事件

      let video = document.createElement('video');
      let canvas = document.createElement('canvas');
      //使用严格模式
      ('use strict');
      video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
      video.setAttribute('src', url);
      video.setAttribute('width', width);
      video.setAttribute('height', height);
      video.currentTime = 1; // 第一帧
      video.preload = 'auto'; //metadata:抓取原数据
       //判断IOS 监听 durationchange或progress  但是在ios会出现黑屏
      if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
    
    
        video.load();
        video.autoplay = true;
        video.muted = true; //静音
        listen = 'loadeddata';
      }
      // 第二版 dataLoad
      video.addEventListener(listen, () => {
    
    
        console.log("我走了");
        canvas.width = width;
        canvas.height = height;
        canvas.getContext('2d').drawImage(video, 0, 0, width, height); //绘制canvas
        dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
        resolve(dataURL);
      });
    } catch (error) {
    
    
      console.log('视频截帧的失败报错:', error);
    }
  });
}

The second type:

export function getFirstImg2(url) {
    
    
  const video = document.createElement("video");
  video.crossOrigin = "anonymous"; // 允许url跨域
  video.autoplay = true; // 自动播放
  video.muted = true; // 静音
  video.src = url;

  return new Promise((resolve, reject) => {
    
    
    try {
    
    
      video.addEventListener(
        "loadedmetadata",
        () => {
    
    
          console.log("loadedmetadata");
          video.currentTime = 2;
          const canvas = document.createElement("canvas");
          video.addEventListener("canplaythrough", () => {
    
    
            console.log("canplaythrough");
            canvas.width = video.videoWidth;
            canvas.height = video.videoHeight;
            canvas
              .getContext("2d")
              .drawImage(video, 0, 0, canvas.width, canvas.height);
            const firstFrame = canvas.toDataURL();
            // console.log(firstFrame); // 输出第一帧画面的Base64编码字符串
            resolve(firstFrame);
          });
        },
        {
    
     once: true }
      );
    } catch (err) {
    
    
      console.error(err);
      reject("");
    }
  });
}

8. Summary

If the above methods are used to indicate that there are asynchronous operations in them, then they should be used to obtain the converted file new Promisewhen calling . .thenOr directly use async awaitthe syntax to receive resolve ()the file returned by the method;

Ensure that the code can run synchronously to avoid unexpected problems;

Guess you like

Origin blog.csdn.net/qq_43886365/article/details/132355364