在前端开发中,文件格式转换是常见需求,比如将用户上传的图片转为base64字符串、将文本文件转为不同编码格式、将二进制数据转为可下载的文件等,js提供了多种原生API可以支撑这些场景的实现。

方案一:使用FileReader转换文本/图片类文件格式
FileReader是js提供的用于读取文件内容的API,支持将文件转换为base64、文本字符串、二进制字符串等多种格式,适合处理用户上传的本地文件。
适用场景
- 将上传的图片文件转为base64字符串用于预览
- 将文本文件转为指定编码的字符串内容
- 读取文件的二进制原始数据
实现示例
以下代码实现将上传的图片文件转换为base64格式:
// 获取文件上传元素
const fileInput = document.querySelector('#fileInput');
fileInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
// 创建FileReader实例
const reader = new FileReader();
// 监听读取完成事件
reader.onload = function(event) {
const base64Str = event.target.result;
console.log('转换后的base64字符串:', base64Str);
// 可以将base64赋值给img标签的src实现预览
const img = document.querySelector('#previewImg');
img.src = base64Str;
};
// 以base64格式读取文件
reader.readAsDataURL(file);
});
方案二:使用Blob对象转换二进制数据为文件格式
Blob对象表示不可变的原始数据,我们可以通过Blob构造新的文件对象,修改其MIME类型实现格式转换,适合将内存中的二进制数据转为指定格式的文件。
适用场景
- 将base64字符串转为可下载的图片文件
- 将JSON数据转为可下载的文本文件
- 修改现有文件的MIME类型实现格式适配
实现示例
以下代码实现将base64字符串转换为png图片文件并触发下载:
function base64ToPngFile(base64Str, fileName) {
// 去掉base64的前缀部分
const base64Data = base64Str.split(',')[1];
// 将base64转为二进制字符串
const binaryStr = atob(base64Data);
// 转为字节数组
const len = binaryStr.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryStr.charCodeAt(i);
}
// 创建Blob对象,指定MIME类型为png
const blob = new Blob([bytes], { type: 'image/png' });
// 创建下载链接
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = fileName || 'output.png';
// 触发下载
a.click();
// 释放URL对象
URL.revokeObjectURL(url);
}
// 调用示例,假设已有base64格式的图片字符串
// base64ToPngFile(existingBase64Str, 'new_image.png');
方案三:使用TextEncoder/TextDecoder转换文本编码格式
TextEncoder和TextDecoder用于处理文本的编码转换,支持将字符串转为UTF-8等编码的字节流,或者将字节流解码为指定编码的字符串,适合处理文本文件的编码转换需求。
适用场景
- 将UTF-8编码的文本转为GBK编码的字节流
- 读取GBK编码的文本文件并转为UTF-8字符串
- 处理不同编码格式的文本数据转换
实现示例
以下代码实现将UTF-8字符串转换为GBK编码的字节数组:
// 注意:原生TextEncoder仅支持UTF-8编码,GBK编码需要引入第三方库如iconv-lite,以下为UTF-8转字节流的示例
function strToUtf8Bytes(str) {
const encoder = new TextEncoder();
// 将字符串编码为UTF-8字节数组
const utf8Bytes = encoder.encode(str);
console.log('UTF-8字节数组:', utf8Bytes);
return utf8Bytes;
}
function utf8BytesToStr(bytes) {
const decoder = new TextDecoder('utf-8');
// 将UTF-8字节数组解码为字符串
const str = decoder.decode(bytes);
console.log('解码后的字符串:', str);
return str;
}
// 调用示例
const testStr = '测试文本转换';
const bytes = strToUtf8Bytes(testStr);
const resultStr = utf8BytesToStr(bytes);
方案四:使用第三方库处理复杂格式转换
如果遇到复杂的文件格式转换,比如将docx转为pdf、将excel转为csv等,原生js API难以支撑,可以引入对应的第三方库实现,这类库通常封装了完整的转换逻辑,使用成本更低。
适用场景
- 办公文档类格式互转(docx、pdf、xlsx等)
- 音视频格式转换(需要结合后端或WebAssembly方案)
- 特殊格式文件的解析与转换
实现示例
以下代码使用SheetJS库实现excel文件转csv格式:
// 首先引入SheetJS库,假设已通过script标签引入xlsx.full.min.js
function excelToCsv(file) {
const reader = new FileReader();
reader.onload = function(e) {
const data = new Uint8Array(e.target.result);
// 读取excel文件
const workbook = XLSX.read(data, { type: 'array' });
// 获取第一个工作表名称
const firstSheetName = workbook.SheetNames[0];
// 获取第一个工作表
const worksheet = workbook.Sheets[firstSheetName];
// 转为csv格式字符串
const csvStr = XLSX.utils.sheet_to_csv(worksheet);
console.log('转换后的csv内容:', csvStr);
// 可以将csv字符串转为Blob文件触发下载
const csvBlob = new Blob([csvStr], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(csvBlob);
const a = document.createElement('a');
a.href = url;
a.download = 'output.csv';
a.click();
URL.revokeObjectURL(url);
};
// 以数组缓冲区格式读取文件
reader.readAsArrayBuffer(file);
}
// 绑定文件上传事件调用
// document.querySelector('#excelInput').addEventListener('change', e => excelToCsv(e.target.files[0]));
方案对比与选择建议
不同方案的适用场景和特点如下,开发者可以根据实际需求选择:
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| FileReader | 本地上传文件转base64、文本、二进制 | 原生API无需引入额外依赖,使用简单 | 仅能处理本地文件,不支持复杂格式转换 |
| Blob对象 | 二进制数据转指定格式文件 | 原生支持,可自定义MIME类型 | 需要手动处理二进制数据转换逻辑 |
| TextEncoder/TextDecoder | 文本编码格式转换 | 原生支持,处理文本编码高效 | 仅支持UTF-8相关编码,复杂编码需第三方库 |
| 第三方库 | 复杂格式如办公文档、音视频转换 | 覆盖场景全,无需自己实现复杂逻辑 | 需要引入额外依赖,增加项目体积 |
在实际开发中,简单的文件格式转换优先使用原生API实现,复杂场景再考虑引入第三方库,同时注意处理文件大小限制和转换过程中的异常捕获,提升功能的稳定性。
JavaScript文件格式转换File_APIBlob对象FileReader修改时间:2026-07-02 03:42:38