Wybieranie plików i korzystanie z nich na lokalnym urządzeniu użytkownika to jedna z najczęściej używanych funkcji w internecie. Pozwala użytkownikom wybierać pliki i przesyłać je na serwer, np. podczas udostępniania zdjęć czy przesyłania dokumentów podatkowych. Umożliwia też witrynom odczytywanie danych i manipulowanie nimi bez konieczności przesyłania danych przez sieć. Na tej stronie pokazujemy, jak używać JavaScriptu do interakcji z plikami.
Nowoczesny interfejs File System Access API
Interfejs File System Access API umożliwia odczyt i zapis w plikach i katalogach w systemie lokalnym użytkownika. Jest dostępny w większości przeglądarek opartych na Chromium, np. Chrome i Edge. Więcej informacji znajdziesz w artykule na temat interfejsu File System Access API.
Interfejs File System Access API nie jest zgodny ze wszystkimi przeglądarkami, dlatego zalecamy użycie browser-fs-access – biblioteki pomocniczej, która korzysta z nowego interfejsu API wszędzie tam, gdzie jest dostępny, i w razie potrzeby powraca do starszych rozwiązań.
Klasyczna praca z plikami
Z tego przewodnika dowiesz się, jak pracować z plikami przy użyciu starszych metod JavaScript.
Wybierz pliki
Są 2 główne sposoby wybierania plików: za pomocą elementu wejściowego HTML oraz strefy przeciągania i upuszczania.
Element wejściowy HTML
Najłatwiejszym sposobem wyboru plików przez użytkowników jest użycie elementu <input type="file">
, który jest obsługiwany w każdej popularnej przeglądarce. Po kliknięciu użytkownik może wybrać plik lub kilka plików, jeśli podany jest atrybut multiple
w interfejsie wyboru plików systemu operacyjnego. Gdy użytkownik zakończy wybieranie plików, w elemencie uruchamia się zdarzenie change
. Listę plików możesz wyświetlić z obiektu event.target.files
, który jest obiektem FileList
.
Każdy element w elemencie FileList
jest obiektem File
.
<!-- The `multiple` attribute lets users select multiple files. -->
<input type="file" id="file-selector" multiple>
<script>
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
console.log(fileList);
});
</script>
Poniższy przykład pozwala użytkownikowi wybrać wiele plików za pomocą wbudowanego interfejsu wyboru plików systemu operacyjnego, a następnie rejestruje każdy wybrany plik w konsoli.
Ogranicz typy plików, które użytkownicy mogą wybierać
W niektórych przypadkach możesz chcieć ograniczyć typy plików, które użytkownicy mogą wybierać. Na przykład aplikacja do edycji obrazów powinna akceptować tylko obrazy, a nie pliki tekstowe. Aby ustawić ograniczenia dotyczące typów plików, dodaj do elementu wejściowego atrybut accept
i określ akceptowane typy plików:
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">
Niestandardowe przeciąganie i upuszczanie
W niektórych przeglądarkach element <input type="file">
jest także celem zrzutu, który umożliwia użytkownikom przeciąganie i upuszczanie plików do aplikacji. Ta funkcja jest jednak niewielka i może być trudna w obsłudze. Zamiast tego, gdy podasz podstawowe funkcje za pomocą elementu <input type="file">
, możesz zapewnić dużą, niestandardową powierzchnię do przeciągania i upuszczania.
Wybierz strefę upuszczania
Powierzchnia upuszczania zależy od konstrukcji aplikacji. Część okna może być tylko powierzchnią, ale możesz wykorzystać całe okno.
Aplikacja Squoosh do kompresji obrazów pozwala przeciągnąć obraz w dowolne miejsce do okna i kliknąć select an image (wybierz obraz), aby wywołać element <input type="file">
. Niezależnie od wybranej strefy upuszczania upewnij się, że użytkownik jest informowany o możliwości przeciągania plików na tę platformę.
Zdefiniuj strefę spadku
Aby włączyć dla elementu funkcję przeciągania i upuszczania, utwórz detektory 2 zdarzeń: dragover
i drop
.
Zdarzenie dragover
aktualizuje interfejs przeglądarki, aby wskazywać, że przeciąganie i upuszczanie plików tworzy kopię pliku. Zdarzenie drop
uruchamia się, gdy użytkownik upuści pliki na powierzchnię. Tak jak w przypadku elementu wejściowego, masz dostęp do listy plików z obiektu event.dataTransfer.files
, który jest obiektem FileList
. Każdy element FileList
jest obiektem File
.
const dropArea = document.getElementById('drop-area');
dropArea.addEventListener('dragover', (event) => {
event.stopPropagation();
event.preventDefault();
// Style the drag-and-drop as a "copy file" operation.
event.dataTransfer.dropEffect = 'copy';
});
dropArea.addEventListener('drop', (event) => {
event.stopPropagation();
event.preventDefault();
const fileList = event.dataTransfer.files;
console.log(fileList);
});
event.stopPropagation()
i event.preventDefault()
zatrzymają domyślne działanie przeglądarki i uruchomią Twój kod. Bez nich przeglądarka w przeciwnym razie opuściłaby stronę i otworzyłaby pliki, które użytkownik przeniósł do okna przeglądarki.
Przykład na żywo znajdziesz w sekcji Niestandardowe przeciąganie i upuszczanie.
A co z katalogami?
Niestety, nie ma dobrego sposobu dostępu do katalogu przy użyciu JavaScriptu.
Atrybut webkitdirectory
elementu <input type="file">
pozwala użytkownikowi wybrać katalog lub katalogi. Jest obsługiwana w większości najpopularniejszych przeglądarek. Nie dotyczy to Firefoksa na Androida i Safari na iOS.
Jeśli włączone jest przeciąganie i upuszczanie, użytkownik może próbować przeciągnąć katalog do strefy upuszczania. Po uruchomieniu zdarzenia „drop” zawiera ono obiekt File
dla katalogu, ale nie zapewnia dostępu do żadnych plików w katalogu.
Odczytywanie metadanych pliku
Obiekt File
zawiera metadane o pliku. Większość przeglądarek podaje nazwę pliku, jego rozmiar i typ MIME, ale zależnie od platformy różne przeglądarki mogą podawać inne lub dodatkowe informacje.
function getMetadataForFileList(fileList) {
for (const file of fileList) {
// Not supported in Safari for iOS.
const name = file.name ? file.name : 'NOT SUPPORTED';
// Not supported in Firefox for Android or Opera for Android.
const type = file.type ? file.type : 'NOT SUPPORTED';
// Unknown cross-browser support.
const size = file.size ? file.size : 'NOT SUPPORTED';
console.log({file, name, type, size});
}
}
Możesz zobaczyć, jak to działa w prezentacji input-type-file
.
Odczytywanie zawartości pliku
Aby odczytać zawartość obiektu File
w pamięci, użyj narzędzia FileReader
. Możesz nakazać usłudze FileReader
odczytywanie pliku jako bufora tablicowego, adresu URL danych lub tekstu:
function readImage(file) {
// Check if the file is an image.
if (file.type && !file.type.startsWith('image/')) {
console.log('File is not an image.', file.type, file);
return;
}
const reader = new FileReader();
reader.addEventListener('load', (event) => {
img.src = event.target.result;
});
reader.readAsDataURL(file);
}
Ten przykład odczytuje parametr File
podany przez użytkownika, przekształca go w adres URL danych i używa tego adresu URL do wyświetlenia obrazu w elemencie img
.
Aby dowiedzieć się, jak sprawdzić, czy użytkownik wybrał plik obrazu, obejrzyj prezentację read-image-file
.
Monitorowanie postępu odczytu pliku
Podczas odczytywania dużych plików warto poinformować użytkownika o tym, jak daleko posunął się odczyt. Aby to zrobić, użyj zdarzenia progress
udostępnionego przez FileReader
. Zdarzenie progress
ma 2 właściwości: loaded
(ilość odczytu) i total
(ilość odczytu).
function readFile(file) {
const reader = new FileReader();
reader.addEventListener('load', (event) => {
const result = event.target.result;
// Do something with result
});
reader.addEventListener('progress', (event) => {
if (event.loaded && event.total) {
const percent = (event.loaded / event.total) * 100;
console.log(`Progress: ${Math.round(percent)}`);
}
});
reader.readAsDataURL(file);
}
Baner powitalny autorstwa Vincenta Boty z serii Unsplash