使用CryptoJS加密视频存Firebase,解密后无法在HTML5 Video播放求助
问题分析与解决方案
你遇到的核心问题是错误地将二进制视频文件当作文本处理,导致原始二进制数据在编码/解码过程中丢失或损坏。视频是二进制格式,不能用readAsText()或UTF-8字符串来传递——这会破坏非文本字节,最终解密后的内容不再是有效的MP4文件。
下面是具体的修复步骤和完整代码:
关键错误点拆解
- 加密阶段:用
reader.readAsText(file)读取视频,将二进制转为UTF-8字符串,丢失了视频中无法被UTF-8正确编码的字节。 - 解密阶段:将解密结果转为UTF-8字符串,再转Blob,这进一步破坏了二进制结构,生成的Blob不是有效的MP4。
- CryptoJS适配:CryptoJS默认处理的是
WordArray类型,而非字符串,直接对文本字符串加密解密会导致数据格式不匹配。
修复后的代码
1. 加密并上传到Firebase Storage
function almacenarFicheroGrabacionVideo(file) { const storageRef = firebase.storage().ref('videos/' + file.name); const reader = new FileReader(); reader.onload = function () { // 将ArrayBuffer转为CryptoJS需要的WordArray const fileWordArray = CryptoJS.lib.WordArray.create(reader.result); // 加密,得到CipherParams对象 const encrypted = CryptoJS.AES.encrypt(fileWordArray, getCookie('key')); // 将加密结果转为Base64字符串(适合存储) const encryptedBase64 = encrypted.toString(); // 上传Base64字符串到Firebase,指定格式为base64 const task = storageRef.putString(encryptedBase64, 'base64'); task.on('state_changed', (snapshot) => { /* 进度处理 */ }, (err) => { console.error('上传错误:', err); }, () => { console.log("文件上传完成"); } ); }; // 用readAsArrayBuffer读取二进制文件,保留原始数据 reader.readAsArrayBuffer(file); }
2. 解密并在HTML5 Video中播放
$scope.verVideo = function() { const videoRef = firebase.storage().ref('videos/').child('Blurred Bokeh Video 2.mp4'); videoRef.getDownloadURL().then((url) => { return fetch(url).then(res => res.text()); // 下载Base64加密字符串 }).then((encryptedBase64) => { // 解密Base64字符串,得到原始的WordArray const decryptedWordArray = CryptoJS.AES.decrypt(encryptedBase64, getCookie('clave')); // 将WordArray转为Uint8Array(二进制数组) const decryptedBytes = new Uint8Array(decryptedWordArray.sigBytes); for (let i = 0; i < decryptedWordArray.sigBytes; i++) { const wordIndex = Math.floor(i / 4); const byteIndex = i % 4; decryptedBytes[i] = (decryptedWordArray.words[wordIndex] >> (8 * (3 - byteIndex))) & 0xff; } // 创建有效的MP4 Blob const videoBlob = new Blob([decryptedBytes], { type: 'video/mp4' }); // 生成Blob URL并赋值给video标签 const videoUrl = URL.createObjectURL(videoBlob); const videoNode = document.getElementsByTagName('video')[0]; videoNode.src = videoUrl; videoNode.load(); // 触发视频加载 // 如果你需要下载功能,保留这段代码 const element = document.createElement('a'); element.href = videoUrl; element.download = 'Blurred Bokeh Video 2.mp4'; element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); }).catch((error) => { console.error('处理错误:', error); }); };
额外说明
- WordArray与二进制转换:CryptoJS的
WordArray是其内部处理二进制的格式,我们需要手动将其转为Uint8Array才能生成有效的Blob。 - Firebase上传格式:用
putString(..., 'base64')告诉Firebase我们上传的是Base64编码的字符串,这样存储和下载时能正确解析。 - 避免文本转换:全程不要用
readAsText()或toString(CryptoJS.enc.Utf8)处理二进制数据,仅在处理真正的文本时使用。
这样修改后,视频的二进制数据会被完整保留,解密后的Blob是有效的MP4文件,就能正常在HTML5 Video标签中播放了。
内容的提问来源于stack exchange,提问作者asierta
相关产品推荐
相关产品推荐

