基于Firestore字段传递Firebase Storage视频报uploadVid未定义错误
错误成因
触发Uncaught ReferenceError: uploadVid is not defined的核心原因是作用域不匹配:
- 你将
uploadVid函数定义在window.onload的回调函数内部,属于该回调的局部函数,仅能在回调内部被访问 - HTML中写的内联事件
onchange="uploadVid(this.files);"执行时,默认在全局window作用域查找uploadVid函数,找不到对应引用就会抛出引用错误
另外你的代码还存在3个会导致后续运行异常的隐藏问题:
- 代码中直接调用
formA.addEventListener,但从未定义过formA变量,提交表单时会触发新的引用错误 storageRef.child('subjectSel.value')传入的是固定字符串,不会读取下拉框选中的实际科目值,所有视频都会被存在同一个路径下产生覆盖- 新版Firebase Storage已废弃
snapshot.downloadURL属性,直接读取该值拿不到文件的合法访问地址
修复方案
推荐使用JS原生绑定事件的方式替代HTML内联事件,无需暴露全局函数,写法更规范,同时修复上述所有隐藏问题:
- 移除HTML中文件输入框上的内联
onchange属性 - 在
window.onload回调内部补全文件输入框、表单元素的DOM引用,直接绑定对应事件 - 修正Storage存储路径、下载URL获取的逻辑错误,提交表单时同步把视频地址存入Firestore,方便后续跨页面调用
修正后的核心代码如下:
修正后的HTML部分(仅修改文件输入框行,其余代码保留)
<div class="txtb"> <!-- 移除原有的内联onchange属性 --> <input type="file" id="file-ip-1" accept="video/mp4"> </div>
修正后的JS部分
window.onload = function() { var subjectSel = document.getElementById("subject"); var bookSel = document.getElementById("book"); var pageSel = document.getElementById("page"); const IGLink = document.querySelector("#IG_link"); // 补全缺失的DOM引用 const fileInput = document.getElementById("file-ip-1"); const videoPreview = document.getElementById('file-ip-1-preview'); const formA = document.querySelector(".login-form"); for (var x in subjectObject) { subjectSel.options[subjectSel.options.length] = new Option(x, x); } subjectSel.onchange = function() { pageSel.length = 1; bookSel.length = 1; for (var y in subjectObject[this.value]) { bookSel.options[bookSel.options.length] = new Option(y, y); } } bookSel.onchange = function() { pageSel.length = 1; var z = subjectObject[subjectSel.value][this.value]; for (var i = 0; i < z.length; i++) { pageSel.options[pageSel.options.length] = new Option(z[i], z[i]); } } // 直接在JS中绑定文件选择事件,无需全局暴露函数 fileInput.onchange = function(e) { const storageRef = firebase.storage().ref(); const file = e.target.files[0]; // 修正路径:使用实际选择的科目值,拼接时间戳+原文件名避免文件覆盖 const videoRef = storageRef.child(`videos/${subjectSel.value}/${Date.now()}_${file.name}`); const task = videoRef.put(file) task.then(snapshot => { console.log(snapshot) // 修正:使用官方提供的getDownloadURL方法获取合法访问地址 return snapshot.ref.getDownloadURL() }).then(url => { videoPreview.setAttribute('src', url) // 将视频地址暂存在DOM上,提交表单时一起存入Firestore videoPreview.dataset.url = url }).catch(err => { console.error('视频上传失败:', err) }) } // 表单提交逻辑 formA.addEventListener('submit', e => { e.preventDefault(); const db = firebase.firestore(); db.collection('videos').add({ subject: subjectSel.value, book: bookSel.value, page: pageSel.value, IGLink: IGLink.value, // 同步存储视频地址,后续其他页面可直接从Firestore读取该地址拉取视频 videoUrl: videoPreview.dataset.url }); }); }
内容的提问来源于stack exchange,提问作者armory victory
相关产品推荐
相关产品推荐

