使用JavaScript上传视频至bunny.net成功但文件为空损坏求解决
解决bunny.net Stream视频上传后为空损坏的问题
问题场景
使用JavaScript上传视频到bunny.net Stream时,上传流程无报错,但最终生成的视频为空且损坏,原代码如下:
const fileInput = document.getElementById('videoFile'); let file = fileInput.files[0]; console.log(file); video_name = file.name; let video; const toBase64 = file => new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result); reader.onerror = error => reject(error); }); async function Main() { video = await toBase64(file); } video = Main(); const options = { method: 'POST', headers: { 'Content-Type': 'application/json', accept: 'application/json', AccessKey: 'e3214df7-7dba-4a74-b93649716004-454b-46c3' }, body: JSON.stringify({ 'title': video_name }), }; result = fetch('https://video.bunnycdn.com/library/390820/videos', options) .then(res => res.json()) .then(res => { videoId = res.guid; console.log(videoId); const options = { method: 'PUT', headers: { AccessKey: 'e3214df7-7dba-4a74-b93649716004-454b-46c3', 'Content-Type': 'application/octet-stream', }, data: video, }; fetch(`https://video.bunnycdn.com/library/390820/videos/${videoId}`, options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); }) .catch(err => console.error(err));
错误原因分析
- 异步处理错误:
Main()是异步函数,直接赋值给video得到的是Promise对象,而非实际文件数据,导致PUT请求发送无效内容。 - DataURL格式错误:
readAsDataURL返回的结果包含data:xxx;base64,前缀,bunny.net的PUT接口需要纯二进制或不带前缀的Base64数据,直接传递会导致文件损坏。 - fetch参数错误:fetch API中没有
data参数,应该使用body字段携带请求内容,原代码中data: video不会被正确识别,导致请求无有效数据。
修正后的代码
直接使用File对象上传二进制数据,无需转Base64,更高效且避免格式问题:
const fileInput = document.getElementById('videoFile'); async function uploadVideo() { const file = fileInput.files[0]; if (!file) return; const videoName = file.name; const accessKey = 'e3214df7-7dba-4a74-b93649716004-454b-46c3'; const libraryId = '390820'; try { // 1. 创建视频条目 const createRes = await fetch(`https://video.bunnycdn.com/library/${libraryId}/videos`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'accept': 'application/json', 'AccessKey': accessKey }, body: JSON.stringify({ title: videoName }) }); const createData = await createRes.json(); const videoId = createData.guid; console.log('创建视频条目成功,ID:', videoId); // 2. 上传视频文件 const uploadRes = await fetch(`https://video.bunnycdn.com/library/${libraryId}/videos/${videoId}`, { method: 'PUT', headers: { 'AccessKey': accessKey, 'Content-Type': 'application/octet-stream' }, body: file // 直接传递File对象作为二进制数据 }); const uploadData = await uploadRes.json(); console.log('视频上传成功:', uploadData); } catch (err) { console.error('上传失败:', err); } } // 绑定上传触发事件(比如按钮点击) document.getElementById('uploadBtn')?.addEventListener('click', uploadVideo);
关键优化点
- 使用
async/await统一处理异步流程,避免Promise回调嵌套和异步顺序错误。 - 直接传递File对象作为PUT请求的
body,无需转Base64,减少数据体积和格式转换错误。 - 完善错误捕获,便于排查问题。
重要注意事项
- AccessKey安全:前端代码直接暴露AccessKey存在被盗用风险,生产环境必须通过后端代理上传请求,由后端携带AccessKey。
- 文件大小限制:bunny.net对单文件上传有大小限制,大文件建议使用分片上传接口。
- Content-Type:PUT请求的
Content-Type需设为application/octet-stream或对应视频MIME类型(如video/mp4)。
内容的提问来源于stack exchange,提问作者Nadeem Aslam
相关产品推荐
相关产品推荐

