Страницы

Поиск по вопросам

среда, 28 ноября 2018 г.

Если выбрать файл в input type file, затем его переименовать или удалить, то как проверить что файла нет?

Берем input type file Выбираем в нем файл (допустим, хотим отправить его на сервер аяксом) Переименуем выбранный файл (или удалим) Жмем кнопку "отправить", которая берет input-type-file и пытается отправить ранее выбранный, но уже не существующий файл. Аякс виснет.
Ума не приложу, как сделать проверку такого варианта развития событий ))
Проверки вроде привычных на размер или имя файла (ниже) НЕ ПОДХОДЯТ:
var fileVal = $file.val(), fileRaw = $file[0].files[0];
if ( fileVal ) {....} if( typeof fileRaw !== 'undefined' && fileRaw.size > 0 ) {....}
Всегда будет TRUE, input-type-file не видит что файла нет, вот вывод в консоль


Сделал вариант решения с использованием API FileReader - идея в том, чтобы попытаться считать файл перед отправкой при помощи этого API, и увидеть, есть ли на момент отправки файл или нет. Есть ответ от ниже Other - он классный, с промисами, плюс в том - что файл не считывается полностью. Я закину сюда свой код, к которому пришел, может кому-то пригодится тоже - без промисов, если файл считывается без ошибок полностью, то только тогда принимается решение - что он есть и можно отправлять его аяксом (файлики априори будут мелкие).
var $file = $("#" + inpFileId), fileVal = $file.val(), fileRaw = $file[0].files[0], formData, reader;
// Простая проверка что файл выбран, поле не пустое: if ( fileVal && typeof fileRaw !== "undefined" && fileRaw.size > 0 ) {
// Проверка, что выбраный файл не был удален после выбора с проверкой поддержки: if ( typeof window.FileReader === "function") { reader = new FileReader(); reader.readAsDataURL(fileRaw);
// Когда файл считался целиком без проблем: reader.onloadend = function () { //console.log("reader.result:", reader.result );
if ( !!reader.result ) { // Строка или NULL, если файла больше нет uploadSampleFileAjax(); } else { $B.alertCreate({ alertTitle: "Ошибка, файл не существует", alertText: "Выбранный файл не удается найти.
Возможно он был удален или переименован.
Выберите файл и повторите отправку." }); } }; } else { uploadSampleFileAjax(); } } else { $B.alertCreate({ alertTitle: "Ошибка, файл не выбран", alertText: "Выберите файл и повторите отправку." }); }


Ответ

Кэширование есть, где-то видел баг на гитхабе по этой теме (в библиотеке какой-то).
Решение, которое первое пришло в голову - определяем что это лиса и попытаться прочитать файл через FileReader
let iFile = document.querySelector('[type="file"]'); let iBtn = document.querySelector('[type="button"]'); let dResult = document.querySelector('div'); let isFF = !!~navigator.userAgent.toLowerCase().indexOf('firefox'); // Флаг лисы; у меня не применяется, ибо демо, но... iBtn.addEventListener('click', function (e) { let files = iFile.files; let result = {}; Promise.all([...files].map((file, i) => { return new Promise(function(ok, fail){ let r = new FileReader(); // Разумеется, читать весь файл не нужно, для этого читаем только первую часть - это уже значит что файл есть, иначе этот обработчик не выполняется; поэтому логгируем существование и прерываем чтение (кому хочется проверять все 10Gb файла впустую?) r.onprogress = function (e) { result[i] = true; r.abort(); ok(); } r.onerror = function (e) { // Файла нет - разговор короткий result[i] = false; ok(); // Не fail(), иначе Promise.all немедленно перейдёт к своему .then не дожидаясь остальных } r.readAsBinaryString(file); }); })).then(e => { dResult.innerHTML = Object.entries(result).map(([i, res]) => `Element #${i} "${files[i].name}": ${res ? 'Available' : 'Something wrong'}`).join('
'); }); }); |


Проверка демо: Выбираем файл (-ы), отсылаем, видим что всё есть, после чего меняем, допустим, имя выбранного файла в файловой системе и пробуем послать ещё раз, не перезагружая и не перевыбирая.

Комментариев нет:

Отправить комментарий