Minio 的 MD5 秒传原理主要基于文件的唯一性校验,利用文件的 MD5 哈希值来判断文件是否已经存在于存储系统中。这样,如果用户尝试上传一个文件,而这个文件的 MD5 值与存储系统中某个文件的 MD5 值相同,系统就可以直接认定这两个文件是完全一样的,从而避免了重复上传,达到“秒传”的效果。下面是一个简单的入门案例说明如何实现这一功能。
MD5秒传原理简述
- 客户端计算 MD5: 用户在上传文件之前,先计算文件的 MD5 哈希值。
- 查询服务器: 客户端将文件的 MD5 值发送给服务器,询问服务器是否有相同 MD5 值的文件。
- 服务器检查: 服务器接收到 MD5 值后,在数据库或元数据索引中查找是否有匹配的记录。
- 若存在,则直接返回该文件的存储位置或访问链接给客户端,视为上传成功(秒传)。
- 若不存在,则返回客户端需要正常上传文件的指示。
- 上传或跳过: 客户端根据服务器响应决定是直接使用返回的链接还是继续上传文件。
入门案例
前端实现
前端需要实现文件 MD5 计算和发送请求检查的功能。可以使用如 spark-md5
这样的库来计算文件的 MD5 值,并通过 AJAX 发送请求。
// 假设使用了 spark-md5 库
import SparkMD5 from 'spark-md5';
function calculateAndCheckMD5(file) {
return new Promise((resolve, reject) => {
const chunkSize = 2097152; // 2MB chunk
const fileReader = new FileReader();
let chunks = [];
let currentChunk = 0;
let spark = new SparkMD5.ArrayBuffer();
fileReader.onload = (e) => {
spark.append(e.target.result); // Append array buffer
chunks[currentChunk] = e.target.result;
currentChunk++;
if (currentChunk < Math.ceil(file.size / chunkSize)) {
loadNext();
} else {
// Calculate final MD5 and send to server
const md5Hash = spark.end();
checkOnServer(md5Hash, resolve, reject);
}
};
fileReader.onerror = reject;
function loadNext() {
const start = currentChunk * chunkSize;
const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(file.slice(start, end));
}
loadNext();
});
}
function checkOnServer(md5Hash, resolve, reject) {
// 发送 AJAX 请求到服务器检查 MD5
$.ajax({
url: '/check_md5',
type: 'POST',
data: { md5: md5Hash },
success: (data) => {
if (data.code === 201) {
// 秒传成功,直接使用返回的文件链接
resolve(data.fileLink);
} else {
// 需要上传,可以在这里启动上传流程
reject(new Error('需要上传'));
}
},
error: reject
});
}
后端实现(伪代码示例)
后端需要提供一个接口来接收 MD5 值,并在数据库中查找是否存在对应的记录。
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/check_md5', methods=['POST'])
def check_md5():
md5 = request.form.get('md5')
# 这里应该是查询数据库的操作,简化示意
if exists_in_database(md5):
# 返回秒传成功的信息,包含文件访问链接
return jsonify({'code': 201, 'fileLink': 'your_file_link_here'})
else:
# 返回需要上传的指示
return jsonify({'code': 200})
if __name__ == '__main__':
app.run(debug=True)
在这个案例中,前端负责计算文件的 MD5 值并发起查询请求,而后端则负责验证该 MD5 值并作出相应处理。如果 MD5 值匹配到现有文件,就实现了秒传,否则客户端会开始常规的文件上传流程。请注意,这只是一个基础示例,实际应用中还需要考虑更多因素,如安全性、性能优化等。