JavaScript/HTML5/jQuery 拖放上传 - “未捕获的类型错误:无法读取未定义的属性‘文件’"

我会提前告知您,我的 JavaScript 经验有限.<小时>目前,我有 JavaScript 代码:

I will advise you prior that I have limited JavaScript experience.


Currently, I have the JavaScript code:

$('#xhr-filebox').bind({
    "dragover": HandleDragEvent,
    "dragleave": HandleDragEvent,
    "drop": HandleDropEvent
});

function HandleDropEvent(e){
    var files = e.target.files || e.dataTransfer.files;
    UploadFile(files[0]);
}

(部分代码省略,如有需要我会补充)

(some code is omitted, but I will add more if you request)

...和 ​​HTML:

...and the HTML:

<div class="filebox" id="xhr-filebox">
    <p id="xhr-action">...or click me to pick one.</p>
</div>

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

However, when I drag a file into it, the Chrome JS console says this:

未捕获的类型错误:无法读取未定义的属性文件"

Uncaught TypeError: Cannot read property 'files' of undefined

然而,它可以在从文件输入读取时获取 FileList 对象.

It can however get the FileList object when reading from a file input.

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

Curiously, when I log the event argument ( console.log(e) ), it logs it as f.event, whereas in a similar script of mine, it logs it as MouseEvent (screenshot: http://i.stack.imgur.com/3krcT.png)

与 jQuery 中的 bind() 函数不同,this 使用 getElementById() 返回的 DOM 对象的 addEventListener() 函数,IE this 是纯 JavaScript.我已经尝试过这种方法,但没有任何新变化.

Unlike the bind() function in jQuery, this uses the addEventListener() function of a DOM object returned by getElementById(), IE this is pure JavaScript. I have tried that method but nothing new happens.

推荐答案

如果 e.target 上不存在 files,则您正在寻找 e.dataTransfer上的>文件 —但是如果 e 上没有 dataTransfer 属性(并且您的屏幕截图中似乎没有),您将尝试取消引用 undefined,导致此错误.

If files doesn't exist on e.target, you're looking for a files on e.dataTransfer — but if there's no dataTransfer property on e (and there doesn't seem to be in your screenshot) you'll try to dereference undefined, resulting in this error.

我将代码更改为:

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 also 不存在,您将获取 filesundefined,而不是错误.

That way, if e.target.files doesn't exist and e.dataTransfer also doesn't exist, you'll get files being undefined, rather than an error.

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

The event object that jQuery gives you is created and normalized by jQuery. Since we know e.dataTransfer doesn't exist on that event object (from your screenshot), my guess is that it's not one of the properties jQuery copies over from the original event object. That's okay, though, because jQuery gives us access to the original event via e.originalEvent. So I'd try:

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 如果它在哪里,或者从 dataTransfer 对象中我们找到它的任何地方(在 e,或在 e.originalEvent).

That grabs files from e.target if that's where it is, or from the dataTransfer object wherever we find it (on e, or on e.originalEvent).

相关文章