На многих веб-сайтах есть форма для загрузки файла. Для некоторых сайтов, таких как OneDrive или Google Диск, загрузка файлов является основной функцией. С течением времени веб-страницы становятся все более интерактивными. Таким образом, пользователи ожидают большего количества взаимодействий, таких как перетаскивание файлов или каталогов или вставка скриншотов.
Давайте посмотрим, что предоставляют браузеры для загрузки файлов!
<form method="post" enctype="multipart/form-data">
<input type="file" name="photo">
<input type="submit" value="Submit">
</form>
Вы можете улучшить это с помощью двух необязательных атрибутов:
multiple
: позволяет выбрать несколько файловaccept
: выберите ожидаемые mime types, например:image/*
,application/pdf
Drag and drop файлов
Большинство пользователей ожидают, что смогут перетаскивать файлы на страницу. Эта функциональность хорошо поддерживается браузерами и очень проста в реализации. Как только вы получите файлы, вам нужно что-то сделать, например, загрузить их в API или прочитать их содержимое с помощью FileReader api.
const dropZone = document.body;
if (dropZone) {
let hoverClassName = 'hover';
dropZone.addEventListener("dragenter", function(e) {
e.preventDefault();
dropZone.classList.add(hoverClassName);
});
dropZone.addEventListener("dragover", function(e) {
e.preventDefault();
dropZone.classList.add(hoverClassName);
});
dropZone.addEventListener("dragleave", function(e) {
e.preventDefault();
dropZone.classList.remove(hoverClassName);
});
// Это самое важное событие, событие, которое дает доступ к файлам
dropZone.addEventListener("drop", function(e) {
e.preventDefault();
dropZone.classList.remove(hoverClassName);
const files = Array.from(e.dataTransfer.files);
console.log(files);
// TODO что-то делает с файлами...
});
}
Вы можете легко загружать файлы в API, используя fetch API:
if (files.length > 0) {
const data = new FormData();
for (const file of files) {
data.append('file', file);
}
fetch('/upload', {
method: 'POST',
body: data
})
.then(() => console.log("file uploaded"))
.catch(reason => console.error(reason));
}
Drag and drop директорий
Google Chrome и Microsoft Edge теперь поддерживают перетаскивание каталогов. Это очень полезно, если вы хотите загрузить свои файлы в OneDrive или Google Диск. API не очень удобен, так как использует функции обратного вызова с рекурсивным деревом, но это не так сложно. Давайте посмотрим на какой-нибудь код:
// drag* события опущены для краткости (получите их из предыдущего раздела).
dropZone.addEventListener('drop', async function(e) {
e.preventDefault();
dropZone.classList.remove(hoverClassName);
console.log(await getFileAsync(e.dataTransfer));
};
async function getFileAsync(dataTranfer) {
const files = [];
for (var i = 0; i < dataTranfer.items.length; i++) {
const item = dataTranfer.items[i];
if (item.kind === 'file') {
if (typeof item.webkitGetAsEntry === 'function'){
const entry = item.webkitGetAsEntry();
const entryContent = await readEntryContentAsync(entry);
files.push(...entryContent);
continue;
}
const file = item.getAsFile();
if (file) { files.push(file); }
}
}
return files;
};
// Возвращает Promise со всеми файлами иерархии каталогов
function readEntryContentAsync(entry) {
return new Promise((resolve, reject) => {
let reading = 0;
const contents = [];
readEntry(entry);
function readEntry(entry) {
if (entry.isFile) {
reading++;
entry.file(file => {
reading--;
contents.push(file);
if (reading === 0) {
resolve(contents);
}
});
} else if (entry.isDirectory) {
readReaderContent(entry.createReader());
}
};
function readReaderContent(reader) {
reading++;
reader.readEntries(function(entries) {
reading--;
for (const entry of entries) {
readEntry(entry);
}
if (reading === 0) {
resolve(contents);
}
});
};
});
};
Теперь вы мастера загружать файлы и каталоги.