React İle Web Uygulamaları İçin Dinamik Bir Çoklu Dosya Yükleme Bileşeni Nasıl Yapılır?

React İle Web Uygulamaları İçin Dinamik Bir Çoklu Dosya Yükleme Bileşeni Nasıl Yapılır?
React İle Web Uygulamaları İçin Dinamik Bir Çoklu Dosya Yükleme Bileşeni Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu projeyi hayata geçirmek için bilgisayarınızda Node.js'in güncel bir sürümünün (LTS) yüklü olması gerekir. Projenizi oluştururken Vite gibi hızlı yapılandırma araçlarını tercih etmeniz önerilir. İhtiyacımız olan temel kütüphane React'in kendisidir ancak dosya işleme süreçlerinde state (durum) yönetimi için useState ve useEffect kancalarını yoğun bir şekilde kullanacağız.

Başlamadan önce terminalinizde şu komutla yeni bir React projesi oluşturabilirsiniz:

npm create vite@latest dosya-yukleme-app -- --template react
cd dosya-yukleme-app
npm install

Bu kurulum, temiz ve hızlı bir geliştirme ortamı sunar. Projenin bağımlılıklarını yükledikten sonra bileşen yapımızı oluşturmaya başlayabiliriz.

Dosya Seçimi ve State Yönetimi

Çoklu dosya yükleme işleminin ilk adımı, HTML input etiketini multiple özelliği ile yapılandırmaktır. React'te bu işlemi yönetirken, seçilen dosyaları bir dizi (array) olarak state içerisinde tutmak en verimli yöntemdir.

import { useState } from 'react';

const FileUploader = () => {
  const [files, setFiles] = useState([]);

  const handleFileChange = (event) => {
    const selectedFiles = Array.from(event.target.files);
    setFiles(selectedFiles);
  };

  return (
    
  );
};

Burada Array.from() kullanarak FileList nesnesini standart bir JavaScript dizisine dönüştürüyoruz. Bu, dosyalar üzerinde map veya filter gibi dizi metotlarını kullanabilmemizi sağlar.

Seçilen Dosyaların Önizlenmesi

Kullanıcıların yükledikleri dosyaları görmeleri, hata payını düşürür. Özellikle resim dosyaları için URL.createObjectURL metodunu kullanarak geçici bir önizleme URL'i oluşturabiliriz. Bu işlem, dosyayı sunucuya göndermeden önce istemci tarafında görmenizi sağlar.

const FilePreview = ({ files }) => {
  return (
    
{files.map((file, index) => (

{file.name} - {(file.size / 1024).toFixed(2)} KB

))}
); };

Bu bileşen, seçilen dosyaların isimlerini ve boyutlarını ekrana yazdırır. Bellek sızıntılarını önlemek için useEffect içerisinde URL.revokeObjectURL metodunu çağırmayı unutmamalısınız.

Dosyaların Sunucuya Gönderilmesi

Dosyaları sunucuya göndermek için FormData nesnesini kullanmalıyız. FormData, dosya verilerini HTTP isteğinin gövdesine (body) doğru bir şekilde paketler. Fetch API kullanarak dosyaları bir API endpoint'ine nasıl göndereceğinizi aşağıda görebilirsiniz.

const uploadFiles = async (files) => {
  const formData = new FormData();
  files.forEach((file) => {
    formData.append('files', file);
  });

  const response = await fetch('/api/upload', {
    method: 'POST',
    body: formData,
  });

  return response.json();
};

Bu örnekte, dosyaları döngüye alarak aynı anahtar (key) ismiyle FormData içerisine ekliyoruz. Sunucu tarafında bu dosyaları "files" anahtarı üzerinden yakalayabilirsiniz.

Yükleme Durumu ve İlerleme Takibi

Büyük dosyalar yüklenirken kullanıcıya bir ilerleme çubuğu (progress bar) göstermek, kullanıcı deneyimini önemli ölçüde artırır. Axios kütüphanesi, onUploadProgress özelliği ile bu süreci kolaylaştırır.

import axios from 'axios';

const uploadWithProgress = (files, setProgress) => {
  const formData = new FormData();
  files.forEach(file => formData.append('files', file));

  axios.post('/api/upload', formData, {
    onUploadProgress: (progressEvent) => {
      const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
      setProgress(percentCompleted);
    }
  });
};

Bu kod bloğu, yükleme yüzdesini hesaplar ve bir state değişkenini güncelleyerek ilerleme çubuğunun dolmasını sağlar.

Karşılaştırma: Dosya Yükleme Yöntemleri

Yöntem Avantajı Dezavantajı
Fetch API Ekstra bağımlılık yok İlerleme takibi manueldir
Axios Dahili ilerleme takibi Ek kütüphane gerektirir
Base64 Dönüşümü Basit JSON yapısı Dosya boyutunu %33 artırır

Güvenlik Uyarısı: Sunucu tarafında dosya yüklemelerini kabul ederken her zaman dosya türü (MIME type) ve dosya boyutu kontrolü yapın. Yalnızca güvenilir dosya uzantılarına izin verin ve sunucu tarafında dosya adlarını yeniden oluşturarak "Path Traversal" saldırılarını engelleyin.

Sıkça Sorulan Sorular

React'te dosya yükleme boyutu nasıl sınırlandırılır?

Dosyaları state'e eklemeden önce file.size özelliğini kontrol ederek belirli bir bayt değerinin üzerindeki dosyaları reddedebilirsiniz.

Çoklu dosya yüklemede aynı dosyayı iki kez seçersem ne olur?

Varsayılan olarak input, aynı dosyayı tekrar seçmenize izin verir. Bunu engellemek için dosyaları state'e eklerken bir "Set" yapısı kullanarak benzersiz dosyaları tutabilirsiniz.

Sunucu tarafında hangi kütüphaneyi kullanmalıyım?

Node.js kullanıyorsanız Multer kütüphanesi, dosya yükleme işlemlerini yönetmek için endüstri standardıdır ve güvenlik için oldukça güçlüdür.

Yükleme sırasında hata oluşursa nasıl yönetirim?

try-catch blokları kullanarak ağ hatalarını yakalamalı ve kullanıcıya anlamlı bir hata mesajı dönmelisiniz.

Dosya önizlemesi neden yavaş çalışıyor?

Çok sayıda yüksek çözünürlüklü görseli aynı anda önizlemeye çalışmak tarayıcı belleğini tüketebilir. Küçük resimler (thumbnail) oluşturmak için canvas API'sini kullanabilirsiniz.

Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce, sunucu tarafı güvenlik doğrulamalarını (dosya tarama, yetkilendirme) mutlaka uygulayın.

İleri Seviye İpuçları: Sürükle-Bırak (Drag-and-Drop) Entegrasyonu

Kullanıcı deneyimini iyileştirmek için standart dosya seçici butonunun yanı sıra, bir sürükle-bırak alanı eklemek oldukça etkilidir. React'te bu işlemi yönetmek için onDragOver, onDragLeave ve onDrop olaylarını kullanırız.

Aşağıdaki örnekte, bir div elementini nasıl bırakma alanı olarak yapılandıracağınızı görebilirsiniz:

const DropZone = ({ onFilesAdded }) => {
  const handleDrop = (e) => {
    e.preventDefault();
    const files = Array.from(e.dataTransfer.files);
    onFilesAdded(files);
  };

  return (
    
e.preventDefault()} onDrop={handleDrop} style={{ border: '2px dashed #ccc', padding: '20px', textAlign: 'center' }} > Dosyaları buraya sürükleyip bırakın
); };

Performans Optimizasyonu: Büyük Dosyalar İçin Chunking (Parçalara Ayırma)

Çok büyük dosyaları tek bir HTTP isteği ile göndermek, ağ kopmaları veya sunucu zaman aşımı (timeout) hatalarına yol açabilir. Bu sorunu aşmak için dosyayı küçük parçalara (chunk) bölerek göndermek en güvenli yöntemdir.

Blob API ile Dosya Parçalama

JavaScript'in Blob.slice() metodunu kullanarak dosyayı belirli boyutlarda parçalara ayırabilir ve her parçayı sırayla sunucuya yükleyebilirsiniz.

const uploadInChunks = async (file) => {
  const CHUNK_SIZE = 1024 * 1024; // 1MB
  const totalChunks = Math.ceil(file.size / CHUNK_SIZE);

  for (let i = 0; i < totalChunks; i++) {
    const start = i * CHUNK_SIZE;
    const end = Math.min(start + CHUNK_SIZE, file.size);
    const chunk = file.slice(start, end);

    const formData = new FormData();
    formData.append('file', chunk);
    formData.append('chunkIndex', i);
    formData.append('fileName', file.name);

    await fetch('/api/upload-chunk', {
      method: 'POST',
      body: formData
    });
  }
};

Güvenlik ve Validasyon Stratejileri

İstemci tarafındaki kontroller (dosya tipi, boyut sınırı) kullanıcıya hızlı geri bildirim vermek için gereklidir ancak asla tek başına yeterli değildir. Üretim ortamında aşağıdaki güvenlik katmanlarını mutlaka uygulamalısınız:

  • MIME Type Kontrolü: Sadece uzantıya değil, dosyanın gerçek içeriğine (Magic Numbers) bakın.
  • Dosya İsmi Sanitizasyonu: Kullanıcı tarafından gönderilen dosya isimlerini sunucuda yeniden adlandırarak "Directory Traversal" saldırılarını önleyin.
  • Antivirüs Taraması: Yüklenen dosyaları sunucuda bir antivirüs motoru (örneğin ClamAV) ile taratın.
  • Depolama Güvenliği: Yüklenen dosyaları web kök dizininin (web root) dışında bir alanda saklayın.

Örnek Güvenlik Tablosu

Kontrol Noktası Yöntem Önemi
Dosya Uzantısı Whitelist (izin verilenler listesi) Yüksek
Dosya Boyutu Sunucu taraflı limit Orta
İçerik Analizi Dosya imza kontrolü Çok Yüksek

Sonuç

React ile dinamik bir çoklu dosya yükleme bileşeni oluşturmak, doğru state yönetimi ve doğru API kullanımı ile oldukça verimli bir süreçtir. Bu rehberde, dosyaları seçmekten sunucuya göndermeye ve ilerleme takibi yapmaya kadar tüm adımları ele aldık. Bir sonraki adım olarak, sürükle-bırak (drag-and-drop) özelliğini ekleyerek kullanıcı deneyimini daha da ileriye taşıyabilirsiniz. Başarılar dilerim.

Bu yazıya tepkinizi paylaşın:
Emre Cansever

Teknik rehberler ve kendin yap (DIY) projeleri üzerine yoğunlaşıyorum. Detaylı ve güvenilir içerikler hazırlayarak okuyucuların teknik sorunlarını çözmelerine yardımcı oluyorum.

Yorumlar (0)

Yorum Yaz