JavaScript / HTML5 / jQuery拖放上传 – “未捕获的TypeError:无法读取未定义的属性’文件’”

在我有限制的JavaScript经验之前,我会告诉你。


目前,我有JavaScript代码:

$('#xhr-filebox').bind({ "dragover": HandleDragEvent, "dragleave": HandleDragEvent, "drop": HandleDropEvent }); function HandleDropEvent(e){ var files = e.target.files || e.dataTransfer.files; UploadFile(files[0]); } 

(省略了一些代码,但如果你要求,我会添加更多代码)

……和HTML:

 

...or click me to pick one.

但是,当我将文件拖入其中时,Chrome JS控制台会说:

未捕获的TypeError:无法读取未定义的属性“文件”

但是,从文件输入读取时,它可以获取FileList对象。

奇怪的是,当我记录事件参数(console.log(e))时,它将其记录为f.event,而在我的类似脚本中,它将其记录为MouseEvent(屏幕截图: http://i.stack.imgur .com / 3krcT.png )

与jQuery中的bind()函数不同,它使用getElementById()返回的DOM对象的addEventListener()函数,IE这是纯JavaScript。 我尝试过这种方法,但没有新的事情发生。

如果e.target上不存在files ,那么你正在e.dataTransfer上查找files – 但是如果e上没有dataTransfer属性(并且你的屏幕截图中似乎没有)你会尝试取消引用undefined ,导致此错误。

我将代码更改为:

 function HandleDropEvent(e){ var files = e.target.files || (e.dataTransfer && e.dataTransfer.files); if (files) { UploadFile(files[0]); } else { // Perhaps some kind of message here } } 

这样,如果e.target.files不存在且e.dataTransfer也不存在,那么您将获得undefined files ,而不是错误。


jQuery为您提供的事件对象由jQuery创建并规范化。 由于我们知道e.dataTransfer不存在于该事件对象上(来自您的屏幕截图),我的猜测是它不是jQuery从原始事件对象复制的属性之一。 不过,这没关系,因为jQuery让我们可以通过e.originalEvent访问原始事件。 所以我试试:

 function HandleDropEvent(e){ var dt = e.dataTransfer || (e.originalEvent && e.originalEvent.dataTransfer); var files = e.target.files || (dt && dt.files); if (files) { UploadFile(files[0]); } else { // Perhaps some kind of message here } } 

它会从e.target files ,如果它位于何处,或者从我们找到它的数据e.originalEvent对象( ee.originalEvent )中获取。

我过去几年一直在使用以下代码:

 var files = e.target.files || (e.dataTransfer ? e.dataTransfer.files : e.originalEvent.dataTransfer.files); 

但是,我最近遇到了一个使用Chrome的问题,其中有e.target.files,但长度为0导致文件为空,即使dataTransfer确实有删除的文件。

所以,我必须使用稍微不同的检查:

 var files = e.target.files; if (!files || files.length === 0) files = (e.dataTransfer ? e.dataTransfer.files : e.originalEvent.dataTransfer.files); 

希望这可以帮助别人。