利用hash对比算法过滤用户上传的相同图片 🖼️
背景 🎯
在实际开发中,我们经常需要防止用户重复上传相同的图片,以节省服务器存储空间并提升用户体验。本文将介绍如何使用图片哈希对比算法来实现这个功能。
实现原理 💡
- 当用户上传图片时,先将图片转换为 base64 格式
- 使用 SparkMD5 算法计算图片的哈希值
- 将哈希值存入 Set 集合中进行去重判断
- 根据判断结果决定是否继续上传流程
代码实现 ⌨️
javascript
// 1. 处理文件输入变化
const handleFileInputChange = async (e) => {
hashFilterSet([...e.target.files]);
};
// 2. 哈希过滤处理
const hashFilterSet = async (arr) => {
let fileList = [];
for (const file of arr) {
try {
const hash = await calculateImageHash(file);
if (uploadedImages.has(hash)) {
console.log('检测到重复图片:', hash);
tip({
type: "warning",
content: "请勿上传相同的图片",
});
} else {
fileList.push(file);
setUploadedImages(new Set([...uploadedImages, hash]));
}
} catch (error) {
console.error('计算图片哈希值出错:', error);
}
}
// 处理通过验证的文件
handlerFiles(fileList);
}
// 3. 计算图片哈希值
const calculateImageHash = (file) => {
return new Promise((resolve, reject) => {
const imgHash = new Image();
imgHash.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = imgHash.width;
canvas.height = imgHash.height;
ctx.drawImage(imgHash, 0, 0, imgHash.width, imgHash.height);
const data = canvas.toDataURL('image/jpeg');
hashString(data).then(resolve);
};
imgHash.onerror = reject;
imgHash.src = URL.createObjectURL(file);
});
}
// 4. 使用 SparkMD5 计算哈希值
const hashString = (str) => {
return new Promise((resolve) => {
const spark = new SparkMD5.ArrayBuffer();
const enc = new TextEncoder();
const data = enc.encode(str);
spark.append(data);
resolve(spark.end());
});
}注意事项 ⚠️
- 需要提前引入 SparkMD5 库
- 图片哈希对比不是完全可靠的,可能存在极少数误判情况
- 对于大图片,建议在计算哈希值之前进行适当压缩
- 建议在服务端也进行一次查重验证,确保数据安全
优化建议 🚀
- 可以考虑使用 Web Worker 来进行哈希计算,避免阻塞主线程
- 可以实现图片预览功能,提升用户体验
- 可以添加上传进度提示
- 可以设置文件大小和类型限制
总结 📝
通过使用哈希对比算法,我们可以有效地过滤重复图片上传。这个方案实现简单,性能较好,适用于大多数图片上传场景。在实际应用中,可以根据具体需求进行适当的调整和优化。