Wybieranie plików na urządzeniu lokalnym użytkownika i wchodzenie z nimi w interakcję to jedna z najczęściej używanych funkcji internetu. Umożliwia użytkownikom wybieranie plików i przesyłanie ich na serwer, na przykład podczas udostępniania zdjęć lub przesyłania dokumentów podatkowych. Umożliwia też witrynom odczytywanie i manipulowanie nimi bez konieczności przesyłania danych przez sieć. Z tej strony dowiesz się, jak używać JavaScriptu do interakcji z plikami.
Nowoczesny interfejs File System Access API
Interfejs File System Access API umożliwia odczytywanie i zapisywanie plików i katalogów w systemie lokalnym użytkownika. Jest dostępny w większości przeglądarek opartych na Chromium, takich jak Chrome i Edge. Więcej informacji znajdziesz w artykule Interfejs File System Access API.
Ponieważ interfejs File System Access API nie jest zgodny ze wszystkimi przeglądarkami, zalecamy używanie biblioteki pomocniczej browser-fs-access, która używa nowego interfejsu API, gdy jest on dostępny, a w przeciwnym razie stosuje starsze metody.
Praca z plikami w klasyczny sposób
Z tego przewodnika dowiesz się, jak wchodzić w interakcję z plikami za pomocą starszych metod JavaScriptu.
Wybierz pliki
Pliki można wybierać na 2 sposoby: za pomocą elementu wejściowego HTML lub za pomocą strefy przeciągania i upuszczania.
Element wejściowy HTML
Najłatwiejszym sposobem wybierania plików przez użytkowników jest użycie elementu
<input type="file">, który jest obsługiwany przez wszystkie główne przeglądarki. Po kliknięciu umożliwia użytkownikowi
wybranie pliku lub wielu plików, jeśli uwzględniono atrybut
multiple
, za pomocą wbudowanego interfejsu wyboru plików systemu operacyjnego. Gdy użytkownik skończy wybieranie pliku lub plików, zostanie wywołane zdarzenie change elementu. Dostęp do listy plików można uzyskać za pomocą event.target.files, który
jest obiektem FileList.
Każdy element w 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 umożliwia użytkownikowi wybranie wielu plików za pomocą wbudowanego interfejsu wyboru plików systemu operacyjnego, a następnie rejestruje każdy wybrany plik w konsoli.
Ograniczanie typów 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
accept
atrybut, aby określić, które typy plików są akceptowane:
<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 też miejscem docelowym,
co umożliwia użytkownikom przeciąganie i upuszczanie plików w aplikacji. To miejsce docelowe
jest jednak małe i może być trudne w użyciu. Zamiast tego po udostępnieniu podstawowych funkcji za pomocą
elementu <input type="file"> możesz udostępnić dużą, niestandardową powierzchnię przeciągania i upuszczania.
Wybierz strefę zrzutu
Powierzchnia zrzutu zależy od projektu aplikacji. Możesz chcieć, aby tylko część okna była powierzchnią zrzutu, ale możesz też użyć całego okna.
Aplikacja do kompresji obrazów Squoosh umożliwia użytkownikowi przeciągnięcie obrazu w dowolne miejsce
okna i kliknięcie Wybierz obraz, aby wywołać element <input type="file">. Niezależnie od tego, co wybierzesz jako strefę zrzutu, upewnij się, że użytkownik wie, że może przeciągać pliki na tę powierzchnię.
Zdefiniuj strefę zrzutu
Aby włączyć element jako strefę przeciągania i upuszczania, utwórz odbiorniki dla
2 zdarzeń: dragover
i drop.
Zdarzenie dragover aktualizuje interfejs przeglądarki, aby wizualnie wskazać, że działanie przeciągania i upuszczania tworzy kopię pliku. Zdarzenie drop jest wywoływane, gdy użytkownik upuści pliki na powierzchnię. Podobnie jak w przypadku elementu wejściowego, możesz
uzyskać dostęp do listy plików z event.dataTransfer.files, który jest
FileList obiektem. Każdy
element w 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()
zatrzymują domyślne działanie przeglądarki i umożliwiają uruchomienie kodu. Bez nich przeglądarka opuściłaby stronę i otworzyła pliki, które użytkownik upuścił w oknie przeglądarki.
Aby zobaczyć demonstrację na żywo, zapoznaj się z sekcją Niestandardowe przeciąganie i upuszczanie.
A co z katalogami?
Niestety nie ma dobrego sposobu na dostęp do katalogu za pomocą JavaScriptu.
Atrybut webkitdirectory
w elemencie <input type="file"> umożliwia użytkownikowi wybranie katalogu
lub katalogów. Jest obsługiwany przez większość głównych przeglądarek
z wyjątkiem Firefoxa na Androida i Safari na iOS.
Jeśli przeciąganie i upuszczanie jest włączone, użytkownik może spróbować przeciągnąć katalog do strefy zrzutu. Gdy zostanie wywołane zdarzenie upuszczania, będzie ono zawierać obiekt File dla katalogu, ale nie zapewni dostępu do żadnych plików w katalogu.
Odczytywanie metadanych pliku
Obiekt File zawiera metadane pliku. Większość przeglądarek podaje nazwę pliku, jego rozmiar i typ MIME, ale w zależności od platformy różne przeglądarki mogą podawać różne 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 to zobaczyć w działaniu w wersji demonstracyjnej input-type-file.
Odczytywanie zawartości pliku
Użyj FileReader, aby
odczytać zawartość obiektu File do pamięci. Możesz poinformować FileReader, aby
odczytał plik jako bufor tablicy,
adres URL danych,
lub tekst:
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 File podany przez użytkownika, a następnie konwertuje go na 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, zapoznaj się z wersją demonstracyjną
read-image-file.
Monitorowanie postępu odczytu pliku
Podczas odczytywania dużych plików warto zapewnić użytkownikowi informacje o postępie odczytu. W tym celu użyj zdarzenia
progress
udostępnianego przez FileReader. Zdarzenie progress ma 2 właściwości: loaded (odczytana ilość) i total (ilość do odczytania).
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);
}