Layui上传组件如何实行上传前的MD5校验来避免重复上传

作者:袖梨 2026-07-02
choose回调是唯一能做MD5校验的时机,因其可访问File对象并用FileReader分片读取二进制内容,结合SparkMD5.ArrayBuffer增量计算,结果挂载到obj上供before拦截或上传使用。

choose 回调是唯一能做 md5 校验的时机

Layui 的 before 回调拿不到 File 对象,doneerror 已经发完请求——防重复必须卡在文件选中后、上传前。只有 choose 能访问 obj.files[0],也才能用 FileReader 分片读取二进制内容。

  • choose 中必须用 File.slice() 切块(推荐 2 <em> 1024 </em> 1024),不能 readAsText(file) 全量读,否则百 MB 文件直接卡死 UI
  • 必须用 SparkMD5.ArrayBuffer 增量追加,每次 spark.append(e.target.result),最后只调一次 spark.end() —— 多调会返回空字符串
  • 计算完的 md5 值要手动挂到 obj 上(如 obj.md5 = md5Value),供后续 before 或上传参数中使用
  • 若需服务端比对去重,记得在 obj.upload() 前把 md5 加入表单:obj.upload({data: {fileMd5: md5Value}})

before 回调里如何利用 MD5 拦截重复上传

before 本身不接触文件内容,但它能拿到你在 choose 中挂载的 obj.md5。此时可发起异步校验,比如查服务端是否已存在该哈希:

  • 必须返回 Promise,且仅 reject 才拦截:return new Promise((resolve, reject) => { $.get('/api/check-md5', {md5: obj.md5}, res => res.exists ? reject('已存在') : resolve()); })
  • 错误写法:return $.get(...).then(() => false) —— 这个 falseresolve 的值,上传照常进行
  • 如果不用异步校验,只是前端简单判断(如黑名单哈希),可同步 return false(要求 Layui ≥ v2.6.8)
  • 注意:多文件场景下,obj.getChooseFiles() 返回的是 FileList,需先转真数组:Array.from(obj.getChooseFiles())

chunked: true 与 MD5 校验的关系

chunked: true 只负责把文件切片发请求,它不生成也不校验 MD5,更不管断点续传。你仍需在 choose 中独立完成 MD5 计算,并把结果传给后端用于分片去重或秒传判定。

  • 后端必须配合实现:收到 fileMd5 后,先查该文件是否已完整上传;若已存在,直接返回成功,跳过所有分片逻辑
  • 若未完整上传但已有部分分片,后端应返回已传分片索引,前端据此跳过对应块 —— 这部分逻辑完全不在 Layui 范围内
  • 不要指望 chunked 自动帮你“认出”重复文件,它连文件名都不校验,只管按序发包

真正的难点不在代码长度,而在分片读取时的内存控制和 spark.end() 的调用时机。很多人卡在第一次调用后第二次返回空值,却没意识到这是 SparkMD5 内部状态清空导致的——拿到值立刻存变量,别等第二次调用。

相关文章

精彩推荐