TypeScript 代码详解:大文件 MD5 异步计算
核心逻辑:通过分片读取文件SparkMd5逐步追加计算,实现大文件 MD5 异步计算,避免内存溢出。(读取二进制分片)、(分片计算MD5)、File.slice(截取文件分片)。异常处理:捕获FileReader读取错误,通过 Promise 的reject抛出,保证代码健壮性。(注:文档部分内容可能由 AI 生成)
TypeScript 代码详解:大文件 MD5 异步计算
return new Promise<string>((resolve, reject) => {
const chunkSize = 1024 * 1024; // 1MB
const spark = new SparkMd5.ArrayBuffer();
const fileReader = new FileReader();
let cursor = 0;
fileReader.onload = function (e: any) {
spark.append(e.target.result);
cursor += chunkSize;
if (cursor < file.size) {
processNextChunk();
} else {
resolve(spark.end()); // 返回MD5哈希值
}
};
fileReader.onerror = function () {
reject(new Error("文件读取错误"));
};
function processNextChunk() {
const chunk = file.slice(cursor, cursor + chunkSize);
fileReader.readAsArrayBuffer(chunk);
}
processNextChunk();
});
}
这段代码的核心作用是异步计算一个文件的 MD5 哈希值,并且采用了分片读取的方式来处理大文件,避免一次性读取整个文件导致内存占用过高。
代码整体功能与逐行解释
首先,先总结这段代码的核心功能:这是一个异步函数 calculateMd5,接收一个 File 对象作为参数,通过分片读取文件内容并逐步计算,最终返回该文件的 MD5 哈希值字符串。这种分片处理的方式特别适合大文件,能有效控制内存使用。
下面是逐行/逐块的详细解释:
async calculateMd5(file: File): Promise<string> {
-
定义一个异步函数
calculateMd5,参数file是浏览器的File对象(通常来自文件上传控件),函数返回一个Promise,最终会解析为 MD5 哈希值的字符串。 -
async关键字标记这是异步函数,函数内部可以使用await,但这里函数体直接返回了一个新的Promise,是异步处理的另一种写法。
return new Promise<string>((resolve, reject) => {
-
函数返回一个新的
Promise实例,泛型<string>表示这个 Promise 最终会返回字符串类型的结果。 -
resolve是 Promise 成功时的回调,用于返回最终的 MD5 值;reject是失败时的回调,用于抛出错误。
const chunkSize = 1024 * 1024; // 1MB
- 定义分片大小为 1MB(1024*1024 字节),表示每次只读取文件的 1MB 内容,避免一次性读取大文件导致内存溢出。
const spark = new SparkMd5.ArrayBuffer();
-
实例化
SparkMd5的ArrayBuffer版本(SparkMd5是一个轻量的 MD5 计算库,运行在浏览器端,支持分片计算)。 -
ArrayBuffer版本适配FileReader读取的ArrayBuffer格式数据,是处理二进制文件的最优选择。
const fileReader = new FileReader();
let cursor = 0;
-
fileReader:浏览器内置的FileReader对象,用于读取文件的二进制内容。 -
cursor(游标):记录当前读取到文件的哪个位置,初始值为 0(从文件开头开始读取)。
fileReader.onload = function (e: any) {
spark.append(e.target.result);
cursor += chunkSize;
if (cursor < file.size) {
processNextChunk();
} else {
resolve(spark.end()); // 返回MD5哈希值
}
};
-
fileReader.onload:FileReader读取完一块内容后的回调函数(异步触发)。-
spark.append(e.target.result):将当前读取到的文件分片(ArrayBuffer格式)追加到SparkMd5实例中,逐步累积计算 MD5。 -
cursor += chunkSize:游标后移,指向下一个分片的起始位置。 -
if (cursor < file.size):判断是否还有未读取的文件内容:-
有:调用
processNextChunk()读取下一个分片。 -
无:调用
spark.end()完成 MD5 计算,并通过resolve返回最终的哈希字符串。
-
-
fileReader.onerror = function () {
reject(new Error("文件读取错误"));
};
fileReader.onerror:FileReader读取文件出错时的回调,通过reject抛出“文件读取错误”的异常,让调用方可以捕获错误。
function processNextChunk() {
const chunk = file.slice(cursor, cursor + chunkSize);
fileReader.readAsArrayBuffer(chunk);
}
-
定义
processNextChunk函数,负责读取下一个文件分片:-
file.slice(cursor, cursor + chunkSize):从文件的cursor位置开始,截取到cursor + chunkSize位置的分片(最后一个分片可能小于 1MB)。 -
fileReader.readAsArrayBuffer(chunk):将截取的分片以ArrayBuffer格式读取(二进制格式),读取完成后会触发onload回调。
-
processNextChunk();
});
}
- 调用
processNextChunk()启动第一个分片的读取,开始整个 MD5 计算流程。
代码执行流程(可视化)
前置条件
要让这段代码正常运行,你需要:
-
在项目中引入
spark-md5库(浏览器端 MD5 计算库):# npm 安装 npm install spark-md5 # 或 yarn yarn add spark-md5 -
代码运行环境是浏览器(因为用到了
FileReader、File等浏览器专属 API,Node.js 环境不适用)。
调用示例
// 假设你有一个文件上传的 input 元素
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
fileInput.addEventListener('change', async (e) => {
const file = fileInput.files?.[0];
if (file) {
try {
const md5 = await calculateMd5(file);
console.log('文件MD5:', md5);
} catch (error) {
console.error('计算MD5失败:', error);
}
}
});
总结
-
核心逻辑:通过分片读取文件 +
SparkMd5逐步追加计算,实现大文件 MD5 异步计算,避免内存溢出。 -
关键API:
FileReader.readAsArrayBuffer(读取二进制分片)、SparkMd5.ArrayBuffer.append/end(分片计算MD5)、File.slice(截取文件分片)。 -
异常处理:捕获
FileReader读取错误,通过 Promise 的reject抛出,保证代码健壮性。
(注:文档部分内容可能由 AI 生成)
更多推荐
所有评论(0)