💁🏻 前言
在前端开发中,经常是需要对图片进行格式转换,其中常见的格式(其中也叫数据类型)包括(File 、Blob 、Base64 、十六进制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不用任何库对图片进行压缩和裁剪的方法,能够帮助我们更好地对一些文件的处理。
☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。