JavaScript/HTML5/jQuery Drag-and-Drop Upload - "Uncaught 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:
<div class="filebox" id="xhr-filebox">
<p id="xhr-action">...or click me to pick one.</p>
</div>
Однако когда я перетаскиваю в него файл, консоль Chrome JS сообщает следующее:
Uncaught TypeError: Невозможно прочитать свойство 'files' из неопределенного
Однако он может получить объект FileList при чтении из файла ввода.
Любопытно, что когда я регистрирую аргумент события ( console.log(e)), он регистрирует его как f.event, тогда как в моем похожем скрипте он регистрирует его как MouseEvent (снимок экрана: )
В отличие от функции bind() в jQuery, здесь используется функция addEventListener() объекта DOM, возвращаемого getElementById(), т.е. это чистый JavaScript. Я попробовал этот метод, но ничего нового не происходит.
2 ответа
Если files
не существует на e.target
вы ищете files
на e.dataTransfer
- но если нет dataTransfer
собственность на e
(а на скриншоте его нет) вы попытаетесь разыменовать 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
также не существует, вы получите files
являющийся undefined
, а не ошибка.
Объект события, который дает вам 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
}
}
Что хватает files
от e.target
если это где он есть, или из dataTransfer
объект, где бы мы его не нашли (на e
или на e.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);
Надеюсь, это может помочь кому-то еще.