前端开发,谈谈图片File、Blob、Base64、Hex格式转换、及压缩裁剪那些事儿

💁🏻 前言

在前端开发中,经常是需要对图片进行格式转换,其中常见的格式(其中也叫数据类型)包括(FileBlobBase64十六进制Hex)。

图片格式转换就是将一种图片格式转换成另一种图片格式的过程。

📖 需求实现

在不同场景下,图片格式的相互转换,实现了以下需求

  • 图片上传 :将选择的图片转换成指定格式(如: File、Blob、Base64等)上传给服务端处理
  • 图片预览 :将选择的图片转换成Base64编码的字符串,以便在页面中显示预览图像,避免服务端的图像请求再展示从而再处理再上传的反复问题。
  • 图片压缩 :将图片转换成指定格式,并控制其质量,达到减小图片大小,从而提高页面的加载速度。
  • 图片处理 :对图片进行处理,如:对图片进行裁剪、缩放、旋转、添加水印等等操作,然后再将处理后的图片转换成指定格式上传给后端储存。
  • 图片转换 :如:png格式转jpg或jpeg格式,或者svg转png、jpg格式,以便满足不同场景不同需求

类型介绍

File

通过用户选择文件后从input[type=file]元素中获取的一个文件对象

属性 描述
name 文件的名称,不包括路径
size 文件的大小(字节)
type 文件的类型(MIME)如 'image/png'、'text/plain'等
lastModified 文件最后的修改时间(Date)

Blob

Blob(Binary large object):二进制大型对象。

blob常常用是数据库用来存储二进制文件的字段类型,如(图片、音频、视频、文档等)。

比如说哔哩哔哩的视频或者图片用的blob格式(blob:xxx),如下:

Base64

一种基于64个可打印字符来表示二进制数据的方法,用于在文本协议中传递二进制数据。如下:

十六进制Hex

十六进制编码(base16),将字节数据中的每4个bit使用数字(0-9)、字母(A-F)共16个字符数等效表示。其中一个字节有8个bit,所以一个字节会被编码成2个hex字符。

一次开发中需要把hex转文件流传给后端,所以这里也记录一下hex的相关转法。

📖 类型转换

file 转 blob

文件流转blob

javascript 复制代码
/**
 * file转blob
 * @param file   {File} 文件
 * @returns blob {Blob} blob
 */

fileToBlob (file) {
    return window.URL.createObjectURL(file)
}

blob 转 file

blob转file

php 复制代码
/**
 * blob转file
 * @param blob       {Blob}   blob
 * @param fileName   {String} 文件名
 * @param mimeType   {String} 文件类型
 * @returns file     {File}   文件
 */

blobToFile (blob, fileName, mimeType) {
    const file = new File([blob], fileName, { type: mimeType })
    return file
}

mimeType有如常见类型:

  • image/jpeg:jpeg格式的图片

  • image/jpg:jpg格式的图片

  • image/png:png格式的图片

  • image/gif:gif格式的图片

  • audio/mpeg: mp3格式的音频文件

  • video/mp4:mp4格式的视频文件

  • application/pdf:pdf文档

  • application/json:json数据

  • text/plain:纯文本文件

  • text/html:html文档

...

file 转 base64

文件流转base64

javascript 复制代码
/**
 * file转base64
 * @param file       {File}    文件
 * @returns promise  {Promise} 返回base64
 */
 
fileToBase64 (file) {
    return new Promise((resolve, reject) => {
        
        // 使用FileReader对象异步读取文件的内容
        const reader = new FileReader()
        let readerResult = ''
        
        // 开始读取
        reader.readAsDataURL(file)
        
        // 操作完成时触发
        reader.onload = function () {
            readerResult = reader.result
        }
        
        // 读取操作发生错误时触发
        reader.onerror = function (error) {
            reject(error)
        }
        
        // 读取操作结束时触发(要么成功、要么失败)
        reader.onloadend = function () {
            resolve(readerResult)
        }
    })
}

接下来,我用ant-design-vue举例子说明文件流转base64这个方法,如下:

ini 复制代码
<a-upload
    name="file"
    accept="image/*"
    @change="handleChange"
>
    <a-button>上传图片</a-button>
</a-upload>
scss 复制代码
handleChange (info) {
    // 文件流 为 info.file.originFileObj
    
    fileToBase64(info.file.originFileObj).then(base64 => {
        // 获取 base64
    })
}

或者

async handleChange (info) {
    // 文件流 为 info.file.originFileObj
    
    // 获取 base64
    const resBase64 = await fileToBase64(info.file.originFileObj)
}

不用上传至服务器处理再放回图片,可直接先把文件流转为base64,进行压缩、旋转、或者改大小等处理,再将处理过后的图片传至服务端。

base64 转 file

base64 转 文件流,先获取文件的类型和后缀,然后通过base64字符串转blob,最后用new File创建一个File文件流对象。代码如下:

javascript 复制代码
/**
 * base64转file
 * @param base64     {String} base64
 * @param fileName   {String} 文件名 
 * @returns file     {File}   文件
 */
 
base64ToFile (base64, fileName = 'file') {
    const arr = base64.split(',')
    
    // 文件类型
    const mime = arr[0].match(/:(.*?);/)[1]
    
    // 文件后缀
    const suffix = mime.split('/')[1]
    
    // base64解码
    const bstr = atob(arr[1])
    
    let n = bstr.length
    
    // 一个8位无符号整型数组
    let u8arr = new Unit8Array(n)
    
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
    }
    
    return new File([u8arr], `${fileName}.${suffix}`, {
        type: mime
    })
}

base64 转 hex

base64 转 hex(十六进制),先使用atob函数将base64字符串解码成二进制数据,再通过toString(16)转成十六进制。

ini 复制代码
/**
 * base64转hex
 * @param base64     {String} base64 
 * @returns hex      {String} hex十六进制
 */
 
base64ToHex (base64) {
    const arr = base64.split(',')
    
    // 对base64编码的字符串进行解码
    const raw = atob(arr[1])
    
    let HEX = ''
    
    for (let i = 0; i < raw.length; i++) {
        // charCodeAt()得到二进制,二进制通过toString(16)转成十六进制
        const _hex = raw.charCodeAt(i).toString(16)
        HEX += (_hex.length === 2 ? _hex : '0' + _hex)
    }
    return HEX.toUpperCase()
}

hex 转 file

这种hex是十六进制字符串,如果想转成file文件流传过去给后端,方法如下:

javascript 复制代码
/**
 * base64转hex
 * @param hex          {String} hex十六进制 
 * @param fileName     {String} 文件名 
 * @param mimeType     {String} 文件类型
 * @returns hex        {String} hex十六进制
 */
 
hexToFile (hexString, fileName, mimeType) {
    // 将十六进制字符串转成字节数组
    const bytes = hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))
    
    // 从字节数组创建一个Blob对象
    const blob = new Blob([new UintBArray(bytes)], { type: mimeType })
    
    // 从Blob创建一个File对象
    const file = new File([blob], fileName, { type: mimeType })
    
    return file
}

图片处理

压缩和裁剪

压缩和裁剪,先把文件流转成base64 ,创建Image 标签,把这个base64通过src 给到这个Image标签;然后通过image.onload()函数 获取图片的尺寸,最后通过canvas.drawImage()绘制 ,设置长度和高度、并通过canvas.toDataURL(file.type, quality)设置质量 。最终将canvas的base64转成文件流格式。


总结

在前端开发中,经常遇到对文件或者图片进行类型转换处理的需求,以上是在开发项目中总结的类型转换方法,以及纯js不用任何库对图片进行压缩和裁剪的方法,能够帮助我们更好地对一些文件的处理。

☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。

相关推荐
余生H15 分钟前
前端Python应用指南(二)深入Flask:理解Flask的应用结构与模块化设计
前端·后端·python·flask·全栈
outstanding木槿20 分钟前
JS中for循环里的ajax请求不数据
前端·javascript·react.js·ajax
酥饼~26 分钟前
html固定头和第一列简单例子
前端·javascript·html
一只不会编程的猫30 分钟前
高德地图自定义折线矢量图形
前端·vue.js·vue
m0_7482509332 分钟前
html 通用错误页面
前端·html
来吧~41 分钟前
vue3使用video-player实现视频播放(可拖动视频窗口、调整大小)
前端·vue.js·音视频
鎈卟誃筅甡1 小时前
Vuex 的使用和原理详解
前端·javascript
呆呆小雅1 小时前
二、创建第一个VUE项目
前端·javascript·vue.js
m0_748239331 小时前
前端(Ajax)
前端·javascript·ajax
Fighting_p1 小时前
【记录】列表自动滚动轮播功能实现
前端·javascript·vue.js