Dropzone.js加载服务器视频缩略图失败及TypeError报错修复问询
解决Dropzone加载视频缩略图及FileReader错误问题
首先,咱们来拆解一下你遇到的两个核心问题:
错误原因分析
你看到的 TypeError: Argument 1 of FileReader.readAsArrayBuffer does not implement interface Blob 错误,根源在于你通过AJAX创建的mockFile是一个普通的JavaScript对象,不是标准的File或Blob类型。而FileReader.readAsArrayBuffer()只能接受Blob/File类型的参数,所以直接传入mockFile必然会报错。
另外,Dropzone能加载图片缩略图是因为你直接调用了thumbnail事件并传入了图片路径,但视频缩略图需要先截取视频帧,你的原逻辑错误地把mock文件当成了本地文件去处理,自然无法生成缩略图。
修复方案
我们需要区分本地上传的文件和从服务器加载的mock文件,分别处理:
1. 完善Mock文件的标记与属性
在AJAX回调里创建mock文件时,添加类型标记和视频类型,方便后续区分:
$.ajax({ url: 'https://localhost/asnaf2019/userpanel/uploader.php', type: 'post', data: {request: 2}, dataType: 'json', success: function(response){ $.each(response, function(key,value) { var mockFile = { name: value.name, type: 'video/mp4', // 根据实际视频类型设置,或从response中获取 path: value.path, isMock: true // 标记这是从服务器加载的mock文件 }; myDropzone_video.emit("addedfile", mockFile); myDropzone_video.emit("complete", mockFile); // 这里不再直接调用thumbnail,交给addedfile事件处理 }); } });
2. 修改addedfile事件处理逻辑
区分mock文件和本地文件,对mock文件直接通过视频URL生成缩略图:
this.on('addedfile', function(origFile) { // 处理从服务器加载的mock视频文件 if (origFile.isMock) { generateVideoThumbnailFromUrl(origFile, origFile.path); return; } // 保留原有的本地文件处理逻辑(只处理本地上传的视频) if (!origFile.type.match(/mp4|MP4/)) { myDropzone_video.enqueueFile(origFile); myDropzone_video.removeFile(origFile); return; } var fileReader = new FileReader(); fileReader.addEventListener("load", function(event) { var origFileIndex = myDropzone_video.files.indexOf(origFile); myDropzone_video.files[origFileIndex].status = Dropzone.ADDED; var blob = new Blob([fileReader.result], {type: origFile.type}); var url = URL.createObjectURL(blob); var video = document.createElement('video'); var timeupdate = function() { if (snapImage()) { video.removeEventListener('timeupdate', timeupdate); video.pause(); } }; var snapImage = function() { var canvas = document.createElement('canvas'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height); var image = canvas.toDataURL(); var success = image.length > 100000; if (success) { myDropzone_video.emit("thumbnail", origFile, image); URL.revokeObjectURL(url); } return success; }; video.addEventListener('loadeddata', function() { if (snapImage()) { video.removeEventListener('timeupdate', timeupdate); } }); video.addEventListener('timeupdate', timeupdate); video.preload = 'metadata'; video.src = url; video.muted = true; video.playsInline = true; video.play(); }); fileReader.readAsArrayBuffer(origFile); }); // 新增:通过视频URL生成缩略图的工具函数 function generateVideoThumbnailFromUrl(file, videoUrl) { var video = document.createElement('video'); var timeupdate = function() { if (snapImage()) { video.removeEventListener('timeupdate', timeupdate); video.pause(); } }; var snapImage = function() { var canvas = document.createElement('canvas'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height); var image = canvas.toDataURL(); var success = image.length > 100000; if (success) { myDropzone_video.emit("thumbnail", file, image); URL.revokeObjectURL(video.src); // 释放浏览器资源 } return success; }; video.addEventListener('loadeddata', function() { if (snapImage()) { video.removeEventListener('timeupdate', timeupdate); } }); video.addEventListener('timeupdate', timeupdate); video.preload = 'metadata'; video.src = videoUrl; video.muted = true; video.playsInline = true; video.crossOrigin = 'anonymous'; // 若视频跨域,需开启此设置并确保服务器允许跨域 video.play(); }
3. 额外注意事项
- 如果视频资源与当前页面跨域,需要在服务器端配置CORS允许访问,同时设置
video.crossOrigin = 'anonymous'。 - 若服务器已经生成了视频缩略图,可以直接在AJAX回调中调用
myDropzone_video.emit("thumbnail", mockFile, 缩略图路径),省去前端截取帧的步骤,效率更高。
内容的提问来源于stack exchange,提问作者mr.titan
相关产品推荐
相关产品推荐

