Membaca file di JavaScript

Memilih dan berinteraksi dengan file di perangkat lokal pengguna adalah salah satu fitur web yang paling umum digunakan. Hal ini memungkinkan pengguna untuk memilih file dan menguploadnya ke server, misalnya, saat berbagi foto atau mengirimkan pajak yang informatif serta dipersonalisasi. Alat ini juga memungkinkan situs membaca dan memanipulasinya tanpa harus untuk mentransfer data di seluruh jaringan. Halaman ini membahas cara menggunakan JavaScript untuk berinteraksi dengan file.

File System Access API modern

File System Access API menyediakan cara untuk membaca dan menulis ke file dan direktori pada sistem lokal pengguna. Tersedia di sebagian besar aplikasi berbasis Chromium browser seperti Chrome dan Edge. Untuk mempelajari lebih lanjut, lihat File System Access API.

Karena File System Access API tidak kompatibel dengan semua browser, kami sebaiknya gunakan browser-fs-access, library helper yang menggunakan API baru di mana pun tersedia dan berada kembali ke pendekatan lama, ketika itu tidak demikian.

Menangani 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 elemen zona tarik lalu lepas.

Elemen input HTML

Cara termudah bagi pengguna untuk memilih file adalah menggunakan <input type="file"> ini, yang didukung di setiap browser utama. Saat diklik, pengguna memungkinkan pengguna memilih satu file, atau beberapa file jika multiple disertakan, menggunakan pilihan file bawaan sistem operasi mereka UI. Setelah pengguna selesai memilih satu atau beberapa file, change elemen jika terjadi kebakaran. Anda dapat mengakses daftar file dari event.target.files, yang adalah 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 operasi UI pemilihan file bawaan sistem dan kemudian log setiap file yang dipilih ke konsol.

Batasi jenis file yang dapat dipilih pengguna

Dalam beberapa kasus, Anda mungkin ingin membatasi jenis file yang dapat dipilih pengguna. Sebagai contoh, aplikasi pengeditan gambar seharusnya hanya menerima gambar, bukan file teks. Untuk menyetel pembatasan jenis file, tambahkan 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, memungkinkan pengguna untuk menyeret dan melepas file ke dalam aplikasi Anda. Namun, target penurunan ini berukuran kecil dan mungkin sulit digunakan. Sebaliknya, setelah Anda menyediakan fitur inti menggunakan elemen <input type="file">, Anda dapat menyediakan elemen tarik lalu lepas kustom yang besar ditampilkan.

Pilih zona pengiriman Anda

Permukaan lepas Anda bergantung pada desain aplikasi. Anda mungkin hanya ingin sebagai bagian dari jendela untuk menjadi permukaan tetesan, tetapi Anda bisa menggunakan seluruh jendela.

Screenshot Squoosh, aplikasi web kompresi gambar.
Squoosh membuat seluruh jendela menjadi zona penurunan.

Dengan aplikasi kompresi gambar Squoosh, pengguna dapat menarik gambar di mana saja ke dan klik select an image untuk memanggil <input type="file"> . Apa pun yang Anda pilih sebagai zona lepas, pastikan jelas bagi pengguna mereka dapat menarik file ke permukaan itu.

Menentukan zona penurunan

Untuk mengaktifkan elemen sebagai zona tarik lalu lepas, buat pemroses untuk dua peristiwa: dragover dan drop. Peristiwa dragover memperbarui UI browser untuk menunjukkan secara visual bahwa tindakan {i>drag-and-drop<i} adalah membuat salinan file. Peristiwa drop diaktifkan setelah pengguna meletakkan file ke permukaan. Seperti halnya elemen input, Anda dapat mengakses daftar file dari event.dataTransfer.files, yang merupakan Objek FileList. Masing-masing item di 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. Tanpa mereka, browser akan keluar dari halaman Anda dan membuka file pengguna masuk 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.

webkitdirectory pada elemen <input type="file"> memungkinkan pengguna memilih direktori atau direktori. Alat ini didukung di sebagian besar browser utama kecuali untuk Firefox untuk Android dan Safari di iOS.

Jika {i>drag-and-drop<i} diaktifkan, pengguna mungkin mencoba untuk menyeret direktori ke {i>drop zone<i}. Saat peristiwa lepas diaktifkan, peristiwa tersebut akan menyertakan objek File untuk direktori, tetapi tidak menyediakan akses ke file mana pun dalam direktori.

Membaca metadata file

Objek File berisi metadata tentang file. Sebagian besar browser berikan nama file, ukuran file, dan jenis MIME, meskipun tergantung di platform ini, browser yang berbeda mungkin memberikan informasi yang berbeda tidak akurat atau tidak sesuai.

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 di input-type-file demo.

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 data URL, 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 kemajuan pembacaan file

Saat membaca {i>file<i} berukuran besar, akan sangat membantu jika Anda memberikan beberapa UX untuk memberi tahu pengguna sejauh mana perkembangan pembacaan. Untuk melakukannya, gunakan progress 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);
}

Banner besar oleh Vincent Botta dari Unsplash