JavaScript FileReader异步问题:文件魔数校验方法始终返回false的解决
文件上传魔数校验异步问题解决方法
问题背景
在实现文件上传类型校验时,除了扩展名检查外加入了魔数校验逻辑,但原代码因FileReader的异步特性,导致校验方法始终返回false,需要将该校验整合到包含文件名合法性、文件大小等同步校验的体系中。
解决方案:将异步校验改为Promise实现
把魔数校验方法改成返回Promise,这样就能和其他同步校验结合,用async/await实现完整的异步校验流程。
修改后的魔数校验方法
function checkFileTypeViaMagicByte(file) { return new Promise((resolve) => { const filereader = new FileReader(); const blob = file.slice(0, 4); filereader.readAsArrayBuffer(blob); filereader.onloadend = (evt) => { if (evt.target.readyState === FileReader.DONE) { const uint = new Uint8Array(evt.target.result); const bytes = Array.from(uint).map(byte => byte.toString(16)); const hex = bytes.join('').toUpperCase(); switch (hex) { case '89504E47': // PNG case '25504446': // PDF case 'FFD8FFDB': // JPEG case 'FFD8FFE0': // JPEG resolve(true); break; default: resolve(false); } } else { resolve(false); } }; // 处理文件读取失败的情况 filereader.onerror = () => resolve(false); }); }
整合到完整校验体系
使用async/await将同步校验(文件名、大小)和异步魔数校验串联起来:
async function validateFile(file) { // 1. 文件名合法性校验(同步) const isValidFilename = /^[a-zA-Z0-9_\-.]+$/.test(file.name); if (!isValidFilename) { return { valid: false, message: '文件名包含非法字符' }; } // 2. 文件大小校验(同步) const maxAllowedSize = 10 * 1024 * 1024; // 限制10MB if (file.size > maxAllowedSize) { return { valid: false, message: '文件大小超过10MB限制' }; } // 3. 魔数校验(异步,需await) const isValidMagicType = await checkFileTypeViaMagicByte(file); if (!isValidMagicType) { return { valid: false, message: '文件类型不符合要求' }; } // 所有校验通过 return { valid: true, message: '文件校验通过' }; }
实际使用示例
在文件上传控件的事件中调用完整校验:
document.getElementById('fileUpload').addEventListener('change', async (e) => { const selectedFile = e.target.files[0]; if (!selectedFile) return; const validationResult = await validateFile(selectedFile); if (validationResult.valid) { // 校验通过,执行上传逻辑 console.log('文件可上传'); } else { // 校验失败,提示用户 alert(validationResult.message); } });
内容的提问来源于stack exchange,提问作者user1107888
相关产品推荐
相关产品推荐

