如何在fileuploader的beforeSend中先执行异步函数再决定上传
解决FileUploader beforeSend异步校验不生效的问题
这个问题我之前也碰到过——很多上传组件的beforeSend方法默认只支持同步逻辑,不会等待你返回的Promise完成就直接发起请求,所以才会出现你说的“返回false仍上传”的情况。下面给你两种可行的解决方案:
方案1:如果组件支持Promise返回值(现代组件大多支持)
把beforeSend改成async函数,用await等待异步校验完成,这样组件会自动等待Promise的结果再决定是否上传:
beforeSend: async function(item, listEl, parentEl, newInputEl, inputEl) { const file = item.file; // 封装音频时长读取逻辑,用URL.createObjectURL更高效 const getAudioDuration = (file) => { return new Promise((resolve, reject) => { const audioUrl = URL.createObjectURL(file); const aud = new Audio(audioUrl); aud.onloadedmetadata = () => { resolve(aud.duration); URL.revokeObjectURL(audioUrl); // 释放临时URL内存 }; aud.onerror = () => { reject(new Error('无法读取音频文件元数据')); URL.revokeObjectURL(audioUrl); }; }); }; try { const duration = await getAudioDuration(file); if (duration > 60) { console.log('音频时长超过60秒,阻止上传'); return false; } else { console.log('音频时长符合要求,允许上传'); return true; } } catch (err) { console.error('校验出错:', err); // 读取失败时也阻止上传 return false; } }
方案2:如果组件不支持Promise,用回调函数控制
有些旧版上传组件会给beforeSend传入一个done回调,你需要在异步操作完成后调用它来通知组件是否继续上传(具体参数要看组件文档,通常是done(true)允许上传,done(false)阻止):
beforeSend: function(item, listEl, parentEl, newInputEl, inputEl, done) { const file = item.file; const getAudioDuration = (file) => { return new Promise((resolve, reject) => { const audioUrl = URL.createObjectURL(file); const aud = new Audio(audioUrl); aud.onloadedmetadata = () => { resolve(aud.duration); URL.revokeObjectURL(audioUrl); }; aud.onerror = () => { reject(new Error('无法读取音频文件')); URL.revokeObjectURL(audioUrl); }; }); }; // 执行异步校验 getAudioDuration(file) .then(duration => { if (duration > 60) { console.log('时长超过60秒,拒绝上传'); done(false); } else { console.log('时长符合要求,允许上传'); done(true); } }) .catch(err => { console.error('校验失败:', err); done(false); // 出错时也阻止上传 }); // 先返回false暂时阻止同步上传,等回调再决定 return false; }
额外优化点
你原来用FileReader.readAsDataURL的方式其实没必要,直接用URL.createObjectURL生成音频临时链接更高效,尤其是大文件时能避免把整个文件转成Base64字符串占用过多内存。
内容的提问来源于stack exchange,提问作者melvnberd
相关产品推荐
相关产品推荐

