常规方案

使用FileReader以utf-8格式读取文件,根据文件内容是否包含乱码字符,来判断文件是否为utf-8。

如果存在,即文件编码非utf-8,反之为utf-8。

代码如下:

const isUtf8 = async (file: File) => {
return await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsText(file); reader.onloadend = (e: any): void => {
const content = e.target.result;
const encodingRight = content.indexOf("") === -1; if (encodingRight) {
resolve(encodingRight);
} else {
reject(new Error("编码格式错误,请上传 UTF-8 格式文件"));
}
}; reader.onerror = () => {
reject(new Error("文件内容读取失败,请检查文件是否损坏"));
};
});
};

该方法问题在于,如果文件非常大,比如几个G,浏览器读到的内容直接放在内存中,fileReader实例会直接触发onerror,抛出错误,有时浏览器会直接崩溃。

大文件方案

对于大文件,可以对文件内容进行抽样,对文件进行切片,这里使用100片。对切出的每片文件再切取前面1kb大小的片段,以string方式读取。如果1024B可能正好切在某个汉字编码的中间,导致以string方式读取时出错,即首尾可能出现,被认为是非utf-8片段。这时可以取1kb对应字符串的前半段,再去判断是否存在。

上述常数可以根据需求进行调整。

代码如下:

const getSamples = (file: File) => {
const filesize = file.size;
const parts: Blob[] = [];
if (filesize < 50 * 1024 * 1024) {
parts.push(file);
} else {
let total = 100;
const sampleSize = 1024 * 1024;
const chunkSize = Math.floor(filesize / total);
let start = 0;
let end = sampleSize;
while (total > 1) {
parts.push(file.slice(start, end));
start += chunkSize;
end += chunkSize;
total--;
}
}
return parts;
}; const isUtf8 = (filePart: Blob) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader(); fileReader.readAsText(filePart); fileReader.onload = (e) => {
const str = e.target?.result as string;
// 大致取一半
const sampleStr = str?.slice(4, 4 + str?.length / 2);
if (sampleStr.indexOf("�") === -1) {
resolve(void 0);
} else {
reject(new Error(编码格式错误,请上传 UTF-8 格式文件"));
}
}; fileReader.onerror = () => {
reject(new Error(文件内容读取失败,请检查文件是否损坏"));
};
});
}; export default async function (file: File) {
const samples = getSamples(file);
let res = true; for (const filePart of samples) {
try {
await isUtf8(filePart);
} catch (error) {
res = false;
break;
}
}
return res;
}

最新文章

  1. 几个常用Json组件的性能测试
  2. java:比较对象
  3. 2.2.5 NIO.2 Path 和 Java 已有的 File 类
  4. 排序算法 -- 数据结构与算法的javascript描述 第12章
  5. iOS-响应上下左右滑动手势
  6. hdu 5874 Friends and Enemies icpc大连站网络赛 1007 数学
  7. MapReduce初级案例
  8. [刷题]算法竞赛入门经典 3-12/UVa11809
  9. Python的几个常用模块
  10. Windows系统上Redis的安装
  11. Delphi 字母 递增 递减算法
  12. [PHP]PHP rpc框架hprose测试
  13. Mycat了解下
  14. openstack学习-Horizon安装(八)
  15. “全栈2019”Java多线程第十九章:死锁详解
  16. Guava包学习-Multimap
  17. mcnp的重复探测器单元计数-fmesh卡的介绍
  18. 关于Ftp服务器
  19. php伪协议
  20. 用xib自定义UIView并在代码中使用--iOS

热门文章

  1. 华为应用市场AppGallery Connect正式推出全新LOGO
  2. Neo4j/cypher学习笔记与学习建议
  3. poj_1700 题解
  4. surging 如何使用流媒体服务
  5. 【DB宝50】Oracle异构平台迁移之完全可传输导出导入(Full Transportable Export &amp; Import)
  6. docker日志设置
  7. UVA11992不错的线段树段更新
  8. 在Windows上使用终端模拟程序连接操作Linux以及上传下载文件
  9. 深入浅出带你玩转sqlilabs(五)-布尔/延时盲注与二次注入
  10. maven下载Oracle jar包