Dosyaları JavaScript'te okuma

Kullanıcının yerel cihazındaki dosyaları seçmek ve dosyalarla etkileşime geçmek, web'in en yaygın kullanılan özelliklerinden biridir. Kullanıcıların, fotoğraf paylaşırken veya vergi belgeleri gönderirken dosyaları seçip bir sunucuya yüklemesine olanak tanır. Ayrıca, sitelerin verileri ağ üzerinden aktarmak zorunda kalmadan okumasına ve değiştirmesine olanak tanır. Bu sayfada, dosyalarla etkileşim kurmak için JavaScript'in nasıl kullanılacağı açıklanmaktadır.

Modern File System Access API

File System Access API, kullanıcının yerel sistemindeki dosya ve dizinleri okumanın ve bu dosyalara yazmanın bir yolunu sağlar. Chrome ve Edge gibi Chromium tabanlı çoğu tarayıcıda kullanılabilir. Bu konu hakkında daha fazla bilgi edinmek için File System Access API başlıklı makaleyi inceleyin.

File System Access API tüm tarayıcılarla uyumlu olmadığından, mevcut olduğu her yerde yeni API'yi kullanan ve mevcut olmadığında eski yaklaşımlara geri dönen bir yardımcı kitaplık olan browser-fs-access'i kullanmanızı öneririz.

Klasik yöntemle dosyalarla çalışma

Bu kılavuzda, eski JavaScript yöntemlerini kullanarak dosyalarla nasıl etkileşime geçeceğiniz gösterilmektedir.

Dosya seç

Dosya seçmenin iki temel yolu vardır: HTML giriş öğesini ve sürükle ve bırak bölgesini kullanmak.

HTML giriş öğesi

Kullanıcıların dosya seçmesinin en kolay yolu, tüm büyük tarayıcılarda desteklenen <input type="file"> öğesini kullanmaktır. Tıklandığında kullanıcının işletim sisteminin yerleşik dosya seçimi kullanıcı arayüzünü kullanarak bir dosya veya multiple özelliği eklenmişse birden fazla dosya seçmesine olanak tanır. Kullanıcı bir veya daha fazla dosya seçmeyi tamamladığında öğenin change etkinliği tetiklenir. Dosya listesine FileList nesnesi olan event.target.files üzerinden erişebilirsiniz. FileList alanındaki her öğe bir File nesnesidir.

<!-- 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>

Aşağıdaki örnekte, kullanıcının işletim sisteminin yerleşik dosya seçim kullanıcı arayüzünü kullanarak birden fazla dosya seçmesi ve ardından seçilen her dosyayı konsola kaydetmesi sağlanmaktadır.

Kullanıcıların seçebileceği dosya türlerini sınırlama

Bazı durumlarda, kullanıcıların seçebileceği dosya türlerini sınırlamak isteyebilirsiniz. Örneğin, bir resim düzenleme uygulaması yalnızca resimleri kabul etmeli, metin dosyalarını kabul etmemelidir. Dosya türü kısıtlamaları belirlemek için hangi dosya türlerinin kabul edildiğini belirtmek üzere giriş öğesine bir accept özelliği ekleyin:

<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">

Özel sürükle ve bırak

Bazı tarayıcılarda <input type="file"> öğesi, kullanıcıların dosyalarını uygulamanıza sürükleyip bırakmasına olanak tanıyan bir bırakma hedefidir. Ancak bu bırakma hedefi küçüktür ve kullanımı zor olabilir. Bunun yerine, <input type="file"> öğesini kullanarak temel özellikleri sağladıktan sonra büyük, özel bir sürükle ve bırak yüzeyi sunabilirsiniz.

Bırakma bölgenizi seçin

Düşürme yüzeyiniz, uygulamanızın tasarımına bağlıdır. Pencerenin yalnızca bir kısmının dosya bırakma yüzeyi olmasını isteyebilirsiniz ancak pencerenin tamamını kullanabilirsiniz.

Resim sıkıştırma web uygulaması Squoosh&#39;un ekran görüntüsü.
Squioosh, pencerenin tamamını bir bırakma bölgesi haline getirir.

Squoosh resim sıkıştırma uygulaması, kullanıcının pencereye bir resim sürüklemesine ve <input type="file"> öğesini çağırmak için resim seç'i tıklamasına olanak tanır. Dosya bırakma bölgesi olarak neyi seçerseniz seçin, kullanıcının bu yüzeye dosya sürükleyebileceğinden emin olun.

Bırakma bölgesini tanımlama

Bir öğeyi sürükle ve bırak bölgesi olarak etkinleştirmek için iki etkinlik için işleyiciler oluşturun: dragover ve drop. dragover etkinliği, sürükle ve bırak işleminin dosyanın bir kopyasını oluşturduğunu görsel olarak belirtmek için tarayıcı kullanıcı arayüzünü günceller. drop etkinliği, kullanıcı dosyaları yüzeye bıraktıktan sonra tetiklenir. input öğesinde olduğu gibi, FileList nesnesi olan event.dataTransfer.files öğesinden dosya listesine erişebilirsiniz. FileList içindeki her öğe bir File nesnesidir.

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() ve event.preventDefault() tarayıcının varsayılan davranışını durdurur ve bunun yerine kodunuzun çalışmasını sağlar. Aksi takdirde tarayıcı, sayfanızdan ayrılır ve kullanıcının tarayıcı penceresine bıraktığı dosyaları açar.

Canlı bir gösterim için Özel sürükle ve bırak bölümüne bakın.

Dizinler ne olacak?

Maalesef JavaScript kullanarak bir dizine erişmenin iyi bir yolu yoktur.

<input type="file"> öğesindeki webkitdirectory özelliği, kullanıcının bir veya daha fazla dizin seçmesine olanak tanır. Android için Firefox ve iOS'teki Safari hariç büyük tarayıcıların çoğunda desteklenir.

Sürükle ve bırak özelliği etkinse kullanıcılar bir dizini bırakma alanına sürüklemeyi deneyebilir. Bırakma etkinliği tetiklendiğinde, dizin için bir File nesnesi içerir ancak dizindeki dosyalardan hiçbirine erişim sağlamaz.

Dosya meta verilerini okuma

File nesnesi, dosyayla ilgili meta verileri içerir. Çoğu tarayıcı dosya adını, dosya boyutunu ve MIME türünü sağlar. Ancak platforma bağlı olarak farklı tarayıcılar farklı veya ek bilgiler sağlayabilir.

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});
  }
}

Bu özelliğin işleyiş şeklini input-type-file demosunda görebilirsiniz.

Dosya içeriğini okuma

File nesnesinin içeriğini belleğe okumak için FileReader özelliğini kullanın. FileReader'e bir dosyayı dizi arabelleği, veri URL'si veya metin olarak okumasını söyleyebilirsiniz:

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);
}

Bu örnekte, kullanıcı tarafından sağlanan bir File okunur, ardından veri URL'sine dönüştürülür ve resmi bir img öğesinde görüntülemek için bu veri URL'si kullanılır. Kullanıcının bir resim dosyası seçtiğini nasıl doğrulayacağınızı öğrenmek için read-image-file demosuna bakın.

Dosya okuma işleminin ilerleme durumunu izleme

Büyük dosyalar okunurken kullanıcıya okuma işleminin ne kadar ilerlediğini bildirmek için kullanıcı deneyimi sunmak yararlı olabilir. Bunun için FileReader tarafından sağlanan progress etkinliğini kullanın. progress etkinliğinin iki özelliği vardır: loaded (okunan miktar) ve total (okunacak miktar).

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);
}

Unsplash'tan Vincent Botta tarafından oluşturulan hero resim