Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Nhận diện file trùng lặp trước khi upload với HTML5 File API

Khi xây dựng file uploader, cần tránh upload file trùng lặp (cùng nội dung). So sánh nội dung file phía client.

Vấn đề

  • Tính hash (MD5, SHA-256) toàn bộ file ở client: tốn CPU, chậm với file lớn (>100MB).
  • So sánh tên file/kích thước: không tin cậy (file khác nhau có thể trùng tên/size).

Giải pháp thực tế

1. Hash mẫu (Sampling Hash) - Cân bằng tốc độ/độ tin cậy

  • Chỉ hash các chunk cố định: ví dụ 1MB đầu, 1MB giữa, 1MB cuối.
  • Kết hợp: hash = hash(first 1MB + last 1MB + size + name).
  • Rất nhanh, độ trùng lặp dương tính (false positive) rất thấp.

2. Sử dụng Web Worker cho hash toàn bộ

  • Đưa việc hash (SparkMD5, crypto.subtle.digest) vào Web Worker để không block UI.
  • Hiển thị progress bar khi hash file lớn.

3. Server-side deduplication (tốt nhất)

  • Client gửi metadata (name, size, sampling hash) trước.
  • Server kiểm tra DB, nếu đã có file giống hệt (so sánh hash đầy đủ server-side), báo "đã tồn tại", client bỏ qua upload.
  • Đảm bảo 100% chính xác, giảm tải client.

Ví dụ: Sampling hash nhanh với SparkMD5

async function quickHash(file) {
  const spark = new SparkMD5.ArrayBuffer();
  const chunkSize = 1024 * 1024; // 1MB
  const totalChunks = Math.ceil(file.size / chunkSize);
  
  // Chỉ hash 3 chunk: đầu, giữa, cuối
  const indices = [0, Math.floor(totalChunks/2), totalChunks-1].filter((v,i,a)=>a.indexOf(v)===i);
  
  for (const i of indices) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const buffer = await file.slice(start, end).arrayBuffer();
    spark.append(buffer);
  }
  return spark.end() + '-' + file.size; // hash + size làm fingerprint
}

Kết luận: Không có "shortcut" hoàn hảo. Kết hợp sampling hash client-side + full hash server-side là cân bằng tốt nhất.