Memilih dan berinteraksi dengan file di perangkat lokal pengguna adalah salah satu fitur web yang paling umum digunakan. Fitur ini memungkinkan pengguna memilih file dan menguploadnya ke server, misalnya, saat membagikan foto atau mengirimkan dokumen pajak. Hal ini juga memungkinkan situs membaca dan memanipulasinya tanpa harus mentransfer data ke seluruh jaringan. Halaman ini menjelaskan cara menggunakan JavaScript untuk berinteraksi dengan file.
File System Access API modern
File System Access API menyediakan cara untuk membaca dari dan menulis ke file serta direktori di sistem lokal pengguna. Fitur ini tersedia di sebagian besar browser berbasis Chromium seperti Chrome dan Edge. Untuk mempelajari lebih lanjut, lihat File System Access API.
Karena File System Access API tidak kompatibel dengan semua browser, sebaiknya gunakan browser-fs-access, library helper yang menggunakan API baru di mana pun tersedia dan kembali ke pendekatan lama jika tidak.
Menggunakan file, dengan cara klasik
Panduan ini menunjukkan cara berinteraksi dengan file menggunakan metode JavaScript lama.
Pilih file
Ada dua cara utama untuk memilih file: menggunakan elemen input HTML, dan menggunakan zona tarik lalu lepas.
Elemen input HTML
Cara termudah bagi pengguna untuk memilih file adalah menggunakan elemen
<input type="file">
, yang didukung di setiap browser utama. Saat diklik, tombol ini memungkinkan pengguna
memilih file, atau beberapa file jika
atribut
multiple
disertakan, menggunakan UI pemilihan file bawaan
sistem operasi mereka. Saat pengguna selesai memilih satu atau beberapa file, peristiwa change
elemen akan diaktifkan. Anda dapat mengakses daftar file dari event.target.files
, yang merupakan objek FileList
.
Setiap item dalam FileList
adalah objek 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>
Contoh berikut memungkinkan pengguna memilih beberapa file menggunakan UI pemilihan file bawaan sistem operasi, lalu mencatat setiap file yang dipilih ke konsol.
Membatasi jenis file yang dapat dipilih pengguna
Dalam beberapa kasus, Anda mungkin ingin membatasi jenis file yang dapat dipilih pengguna. Misalnya, aplikasi pengeditan gambar hanya boleh menerima gambar, bukan file teks. Untuk menetapkan
batasan jenis file, tambahkan
atribut
accept
ke elemen input untuk menentukan jenis file yang diterima:
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">
Tarik lalu lepas kustom
Di beberapa browser, elemen <input type="file">
juga merupakan target lepas,
yang memungkinkan pengguna menarik lalu melepas file ke aplikasi Anda. Namun, target lepas ini
kecil dan dapat sulit digunakan. Sebagai gantinya, setelah menyediakan fitur inti menggunakan
elemen <input type="file">
, Anda dapat menyediakan platform tarik lalu lepas
kustom yang besar.
Pilih zona drop Anda
Permukaan drop Anda bergantung pada desain aplikasi Anda. Anda mungkin hanya ingin bagian jendela menjadi platform drop, tetapi Anda dapat menggunakan seluruh jendela.
Aplikasi kompresi gambar Squoosh memungkinkan pengguna menarik gambar ke mana saja ke dalam
jendela, dan mengklik pilih gambar untuk memanggil elemen
<input type="file">
. Apa pun yang Anda pilih sebagai zona lepas, pastikan pengguna
dapat menarik file ke platform tersebut.
Menentukan zona drop
Untuk mengaktifkan elemen sebagai zona tarik lalu lepas, buat pemroses untuk
dua peristiwa: dragover
dan drop
.
Peristiwa dragover
memperbarui UI browser untuk secara visual menunjukkan bahwa
tindakan tarik lalu lepas membuat salinan file. Peristiwa drop
diaktifkan
setelah pengguna meletakkan file ke platform. Seperti elemen input, Anda
dapat mengakses daftar file dari event.dataTransfer.files
, yang merupakan
objek FileList
. Setiap
item dalam FileList
adalah objek 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()
dan event.preventDefault()
menghentikan perilaku default browser dan membiarkan kode Anda berjalan. Tanpanya, browser akan keluar dari halaman Anda dan membuka file yang di-drop pengguna ke jendela browser.
Untuk demonstrasi langsung, lihat Tarik lalu lepas kustom.
Bagaimana dengan direktori?
Sayangnya, tidak ada cara yang baik untuk mengakses direktori menggunakan JavaScript.
Atribut webkitdirectory
di elemen <input type="file">
memungkinkan pengguna memilih direktori
atau beberapa direktori. Fitur ini didukung di sebagian besar browser utama
kecuali Firefox untuk Android dan Safari di iOS.
Jika tarik lalu lepas diaktifkan, pengguna mungkin mencoba menarik direktori ke
zona lepas. Saat peristiwa drop diaktifkan, peristiwa tersebut akan menyertakan objek File
untuk
direktori, tetapi tidak memberikan akses ke file apa pun dalam direktori.
Membaca metadata file
Objek File
berisi metadata tentang file. Sebagian besar browser
memberikan nama file, ukuran file, dan jenis MIME, meskipun bergantung
pada platform, browser yang berbeda mungkin memberikan informasi
yang berbeda atau tambahan.
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});
}
}
Anda dapat melihat cara kerjanya dalam demo
input-type-file
.
Membaca konten file
Gunakan FileReader
untuk
membaca konten objek File
ke dalam memori. Anda dapat memberi tahu FileReader
untuk
membaca file sebagai buffer array,
URL data,
atau teks:
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);
}
Contoh ini membaca File
yang disediakan oleh pengguna, lalu mengonversinya menjadi URL
data, dan menggunakan URL data tersebut untuk menampilkan gambar dalam elemen img
.
Untuk mempelajari cara memverifikasi bahwa pengguna telah memilih file gambar, lihat
demo read-image-file
.
Memantau progres pembacaan file
Saat membaca file besar, sebaiknya berikan beberapa UX untuk memberi tahu pengguna
progres pembacaan. Untuk itu, gunakan peristiwa
progress
yang disediakan oleh FileReader
. Peristiwa progress
memiliki dua properti:
loaded
(jumlah yang dibaca) dan total
(jumlah yang akan dibaca).
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);
}
Gambar hero oleh Vincent Botta dari Unsplash