数据格式转换
Buffer 和 string
const str = "Hello有趣的12"
const buffer = Buffer.from(str)
console.log(buffer)
// <Buffer 48 65 6c 6c 6f e6 9c 89 e8 b6 a3 e7 9a 84 31 32>
console.log(buffer.toString())
// Hello有趣的12如下的方法是等价的:
console.log(readFileSync('./public/image/xxx.png').toString())
console.log(readFileSync('./public/image/xxx.png', 'utf-8'))甚至可以拓展更深:
type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "base64url" | "latin1" | "binary" | "hex";
const encoding: BufferEncoding
console.log(readFileSync('./public/image/xxx.png').toString(encoding))
console.log(readFileSync('./public/image/xxx.png', encoding))Buffer 和 Base64
例如从本地读取一张图片,并且得到 Base64 的格式, 这里使用了 broofa/mime 来得到资源的 mime 类型
import { readFileSync } from 'fs'
import mime from 'mime'
const filePath = '../public/avatar.png'
const stream = readFileSync(filePath)
// 将图片数据转换为 Base64 字符串
const base64String = Buffer.from(stream).toString('base64')
const base64Path = `data:${mime.getType(filePath)};base64,${base64String}`
console.log(base64Path)
// data:image/png;base64,iVBORw0KGgoAAAA...将 Base64 写入文件
const base64Data = 'data:image/png;base64,iVBORw0KGgoAAAANSUh...'
const base64Image = base64Data.split(';base64,').pop()!
writeFileSync('./avatar.png', base64Image, { encoding: 'base64' })Stream 和 Blob
场景:通常使用 axios + stream 的方式接收一些来自后端的二进制信息
const { data: stream } = await axios.post(
`https://path/from/some/server`,
{
query: 'xxx',
},
{
headers: {
'content-type': 'application/json',
},
responseType: 'stream',
},
);
const response = new Response(stream);
// 然后,使用 Response.blob() 方法将其转换为 Blob 对象
const blob = await response.blob();
// 例如还可以使用 FormData 可以将 blob 数据传给 CDN 服务
const fd = new FormData()
fd.append('file', blob)
await axios.post('https://path/to/your/server', fd, {
headers: {
// 'content-type': 'multipart/form-data',
},
})Stream 和 Buffer
Stream 转为 Buffer
Stream 的来源可以是任意的, 例如从接口返回:
const { data: stream } = await axios.post(
`https://path/from/some/server`,
{
query: 'xxx',
},
{
headers: {
'content-type': 'application/json',
},
responseType: 'stream',
},
);或者是本地的 Buffer
const stream = new Readable()
stream.push('Hello, ')
stream.push('world!')
stream.push(null) // 表示数据结束然后可以使用 stream.on 来监听数据流, 并将数据流转换为 Buffer
const writableBuffer = []
stream.on('data', (chunk) => {
writableBuffer.push(chunk);
});
stream.on('end', () => {
const bufferData = Buffer.concat(writableBuffer);
console.log(bufferData);
});浏览器中 Blob
在文件上传的场景中,通过 <input type="file" /> 读取到的 files 就是 File 类型的数据, File 继承自 Blob, 所以我们可以将 File 设置为 FormData 的 value,来进行文件的上传
<h2>文件上传</h2>
<input type="file" id="fileInput">
<button id="uploadButton">上传文件</button>
<div id="status"></div>
<script>
const fileInput = document.getElementById('fileInput')
const uploadButton = document.getElementById('uploadButton')
const status = document.getElementById('status')
uploadButton.addEventListener('click', async () => {
const file = fileInput.files[0]
if (!file) {
status.textContent = '请选择文件'
return
}
console.log(file instanceof File, file instanceof Blob) // => true true
// const formData = new FormData()
// formData.append('file', file)
})
</script>base64ToFile
下面是一个在浏览器中,将图片的 base64 转为 File 对象的例子
export function base64ToFile({ base64, fileType }: { base64: string; fileType: string }) {
const bytes = window.atob(base64);
const ab = new ArrayBuffer(bytes.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
const type = fileType === 'jpg' ? 'jpeg' : fileType;
const blobFile: ExtendedBlob = new Blob([ia], { type: 'image/' + type });
blobFile.lastModifiedDate = new Date();
blobFile.name = `img_${new Date()}.${type || 'jpg'}`;
return new File([blobFile], blobFile.name, { type: 'image/' + type, lastModified: Date.now() });
}
// source: https://peterroe.icu/download.png
const base64Str = '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'
const file = base64ToFile({
base64: base64Str,
fileType: 'png'
})用 FileReader 读取 file 得到 base64,然后展示:
<img class="preview" />
<script>
const reader = new FileReader();
reader.onload = function (event) {
document.querySelector('.preview').src = event.target.result;
};
reader.readAsDataURL(file)
</script>