Gereksinimler ve Ön Hazırlık
Bu projeyi hayata geçirmek için herhangi bir dış kütüphaneye (jQuery veya React gibi) ihtiyacınız yoktur. Saf JavaScript (Vanilla JS) kullanarak performanslı bir yapı kuracağız. Çalışma ortamınızda modern bir tarayıcı (Chrome, Firefox veya Edge) ve temel seviyede HTML/CSS bilginizin olması yeterlidir.
- Modern bir kod editörü (VS Code önerilir).
- Temel HTML5 yapısı ve CSS bilgisi.
- JavaScript ES6+ sözdizimi (Arrow functions, const/let, template literals).
- Dosya yükleme işlemlerini test etmek için yerel bir sunucu (Live Server eklentisi kullanabilirsiniz).
Adım 1: HTML Yapısını Oluşturma
İlk adım olarak, kullanıcının dosya seçebileceği veya sürükleyip bırakabileceği bir kapsayıcı (container) oluşturuyoruz. Bu alan, etkileşimin merkezi olacaktır.
Dosyaları buraya sürükleyin veya tıklayın
Burada input etiketini hidden (gizli) yaparak, kullanıcıya daha şık bir arayüz sunuyoruz. Dosya listesinin görüneceği file-list div'i ise dinamik içerik için kullanılacaktır.
Adım 2: Sürükle ve Bırak (Drag and Drop) Etkileşimi
Kullanıcıların dosyaları sürükleyip bırakabilmesi için dragover ve drop olaylarını (event) dinlememiz gerekir. JavaScript ile bu olayları yakalayarak varsayılan tarayıcı davranışlarını engellemeliyiz.
const panel = document.getElementById('upload-panel');
const input = document.getElementById('file-input');
panel.addEventListener('dragover', (e) => {
e.preventDefault();
panel.classList.add('active');
});
panel.addEventListener('dragleave', () => {
panel.classList.remove('active');
});
panel.addEventListener('drop', (e) => {
e.preventDefault();
panel.classList.remove('active');
const files = e.dataTransfer.files;
handleFiles(files);
});
Yukarıdaki kodda e.preventDefault() kullanımı kritiktir; aksi takdirde tarayıcı dosyayı yeni bir sekmede açmaya çalışır. active sınıfı ile kullanıcıya görsel geri bildirim sağlıyoruz.
Adım 3: Dosyaları İşleme ve Önizleme
Dosyalar seçildiğinde veya bırakıldığında, bu dosyaların bilgilerini alıp ekrana yansıtmamız gerekir. handleFiles fonksiyonu ile dosya listesini döngüye alarak DOM elemanları oluşturacağız.
function handleFiles(files) {
const list = document.getElementById('file-list');
[...files].forEach(file => {
const item = document.createElement('div');
item.className = 'file-item';
item.innerHTML = `${file.name} Sil`;
list.appendChild(item);
});
}
Burada [...files] kullanımı, FileList nesnesini bir diziye dönüştürerek forEach metodunu kullanabilmemizi sağlar.
Adım 4: Güvenlik ve Dosya Doğrulama
Dosya yükleme işlemlerinde güvenlik en önemli konudur. İstemci tarafında yapılan kontroller sadece kullanıcı deneyimi içindir; gerçek güvenlik sunucu tarafında (backend) yapılmalıdır. Ancak, zararlı dosya tiplerini engellemek için basit bir filtreleme ekleyebiliriz.
Kritik Uyarı: İstemci tarafında yapılan hiçbir dosya tipi veya boyut kontrolü güvenli değildir. Sunucunuzda mutlaka MIME tipi kontrolü ve dosya içeriği doğrulama (Magic bytes kontrolü) yapın. Aksi takdirde sunucunuza zararlı scriptler yüklenebilir.
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'application/pdf'];
const MAX_SIZE = 5 * 1024 * 1024; // 5MB
function validateFile(file) {
if (!ALLOWED_TYPES.includes(file.type)) return false;
if (file.size > MAX_SIZE) return false;
return true;
}
Bu fonksiyon ile seçilen dosyanın türünü ve boyutunu kontrol ederek, geçersiz dosyaların listeye eklenmesini engelleyebilirsiniz.
Adım 5: Dosya Yükleme Yöntemlerinin Karşılaştırılması
Dosyaları sunucuya göndermek için farklı yöntemler mevcuttur. İhtiyacınıza göre en uygun olanı seçebilirsiniz.
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| XMLHttpRequest | Geniş tarayıcı desteği | Karmaşık sözdizimi |
| Fetch API | Modern ve temiz sözdizimi | İlerleme çubuğu desteği sınırlı |
| FormData + Fetch | Dosya yükleme için en ideal | Eski tarayıcılarda desteklenmez |
Adım 6: Sunucuya Dosya Gönderme
Dosyaları sunucuya FormData nesnesi ile göndermek, standart bir HTML formunun davranışını taklit etmemizi sağlar.
async function uploadFiles(files) {
const formData = new FormData();
for (let file of files) {
formData.append('files[]', file);
}
const response = await fetch('/upload-endpoint', {
method: 'POST',
body: formData
});
return await response.json();
}
Bu kod bloğu, seçilen dosyaları files[] anahtarı ile sunucuya asenkron olarak gönderir. Sunucunuzun bu isteği karşılayacak şekilde yapılandırılmış olması gerekir.
Sıkça Sorulan Sorular
Dosya yükleme panelinde ilerleme çubuğunu (progress bar) nasıl eklerim?
XMLHttpRequest kullanarak upload.onprogress olayını dinleyerek yükleme yüzdesini hesaplayabilirsiniz. Fetch API ile bu işlem için ReadableStream kullanmanız gerekir.
Birden fazla dosya yüklemeyi nasıl kısıtlarım?
Input etiketindeki multiple niteliğini kaldırarak veya handleFiles fonksiyonunda files.length kontrolü yaparak kısıtlama sağlayabilirsiniz.
Dosya isimleri çakışırsa ne yapmalıyım?
İstemci tarafında isimleri değiştirmek yerine, sunucu tarafında dosyaları benzersiz ID'ler (UUID) ile kaydetmek en güvenli yöntemdir.
Büyük dosyalar için ne yapmalıyım?
Büyük dosyaları parçalara bölerek (chunking) yüklemek, bağlantı kopmalarında veri kaybını önler ve sunucu üzerindeki yükü dengeler.
XSS saldırılarına karşı nasıl önlem alırım?
Kullanıcı tarafından yüklenen dosyaların isimlerini doğrudan HTML içine yazdırmayın. İsimleri sanitize edin veya sadece sunucuda saklanan referansları kullanın.
İleri Seviye Optimizasyon: Büyük Dosyalar İçin Chunking (Parçalara Ayırma)
Dosya yükleme süreçlerinde en büyük zorluk, ağ kopmaları veya sunucu zaman aşımı (timeout) hatalarıdır. Özellikle birkaç yüz megabaytlık dosyaları tek bir HTTP isteğiyle göndermek, hem istemci hem de sunucu tarafında ciddi performans darboğazlarına yol açar. Bu sorunu aşmak için Blob API kullanarak dosyayı küçük parçalara (chunks) ayırıp sırayla göndermek en profesyonel yaklaşımdır.
Chunking Mantığı ile Yükleme
Dosyayı 1MB'lık parçalara bölerek yüklemek, herhangi bir parça başarısız olduğunda sadece o parçayı tekrar göndermenize olanak tanır. Aşağıda, temel bir dosya parçalama mantığını gösteren JavaScript örneği yer almaktadır:
function uploadFileInChunks(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('index', i);
formData.append('filename', file.name);
fetch('/upload-endpoint', {
method: 'POST',
body: formData
}).then(response => {
console.log(`Parça ${i} yüklendi.`);
});
}
}
Dosya Yükleme Paneli İçin Hata Ayıklama ve İzleme Stratejileri
Dinamik bir arayüzde kullanıcıya hata mesajlarını doğru iletmek, uygulamanın güvenilirliğini artırır. Sadece "yükleme başarısız" demek yerine, hatanın kaynağını (ağ hatası, dosya boyutu sınırı, sunucu hatası) belirlemek için XMLHttpRequest veya fetch API'sinden gelen yanıtları detaylıca analiz etmelisiniz.
Hata Yönetimi İçin En İyi Uygulamalar
- Ağ Durumunu İzleme: Kullanıcının internet bağlantısı koptuğunda yüklemeyi duraklatın ve bağlantı geri geldiğinde "Devam Et" seçeneği sunun.
- Sunucu Yanıt Kodları: 413 (Payload Too Large) hatası aldığınızda, kullanıcıya dosya boyutunun sunucu limitlerini aştığını net bir şekilde belirtin.
- Zaman Aşımı (Timeout): Fetch API doğrudan timeout desteklemez; bu nedenle
AbortControllerkullanarak uzun süren yüklemeleri iptal edebilirsiniz.
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 saniye limit
fetch('/upload', {
method: 'POST',
body: formData,
signal: controller.signal
}).catch(err => {
if (err.name === 'AbortError') {
console.error('Yükleme zaman aşımına uğradı.');
}
});
Bu teknikler, özellikle kurumsal düzeydeki dosya yönetim panellerinde kullanıcı deneyimini iyileştiren kritik mekanizmalardır. Uygulamanızın ölçeklenebilirliğini artırmak için bu yapıları sunucu tarafındaki bir Queue (Kuyruk) sistemiyle birleştirmeniz önerilir.
Sonuç
JavaScript ile dinamik bir dosya yükleme paneli oluşturmak, hem kullanıcı deneyimini zenginleştirir hem de uygulamanıza profesyonel bir dokunuş katar. Bu rehberde, temel sürükle-bırak mantığından dosya doğrulama ve sunucuya gönderme süreçlerine kadar kritik adımları inceledik.
Yasal Sorumluluk Reddi: Bu rehberde sunulan kod örnekleri eğitim amaçlıdır. Uygulamanızın üretim (production) ortamında kullanılmadan önce, sunucu tarafında gerekli tüm güvenlik kontrollerinin (dosya türü, boyut, yetkilendirme ve XSS/CSRF koruması) yapıldığından emin olun.
Bir sonraki adım olarak, yüklenen dosyalar için bir "İptal Et" butonu ekleyebilir veya FileReader API kullanarak görsel dosyalar için anlık önizleme (thumbnail) oluşturmayı deneyebilirsiniz. Başarılar dilerim.


Yorumlar (0)
Yorum Yaz