Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce bilgisayarınızda Node.js'in güncel bir LTS (Long Term Support) sürümünün yüklü olduğundan emin olmalısınız. Çalışma ortamınızı hazırlamak için terminalinizde aşağıdaki adımları izleyin.
# Proje klasörünü oluşturun
mkdir node-dosya-yukleme
cd node-dosya-yukleme
# Projeyi başlatın
npm init -y
# Gerekli paketleri kurun
npm install express multer
Bu komutlar, projenizin temelini atar ve Express (web sunucusu çatısı) ile Multer (dosya yükleme işlemlerini yöneten middleware) kütüphanelerini projenize dahil eder. 2026 yılı itibarıyla modüler yapıları korumak adına package.json dosyanıza "type": "module" ekleyerek ES Modules (ESM) sözdizimini kullanmanızı öneririm.
Multer Middleware Yapılandırması
Multer, multipart/form-data türündeki verileri işlemek için kullanılan standart bir Node.js kütüphanesidir. Dosyaların nereye kaydedileceğini ve isimlerinin nasıl olacağını belirlemek için bir depolama (storage) motoru yapılandırmamız gerekir.
import multer from 'multer';
import path from 'path';
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/'); // Dosyaların kaydedileceği klasör
},
filename: (req, file, cb) => {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
}
});
const upload = multer({ storage: storage });
Yukarıdaki kod bloğu, dosyaların üzerine yazılmasını engellemek için benzersiz isimler oluşturur. destination fonksiyonu, dosyaların fiziksel olarak sunucuda hangi dizine gideceğini belirtir. filename fonksiyonu ise çakışmaları önlemek için zaman damgası ve rastgele sayıları birleştirir.
Dosya Yükleme Rotalarının Oluşturulması
Sunucunuzda bir endpoint (uç nokta) oluşturarak istemciden gelen dosyayı kabul etmeliyiz. Express uygulamasına bu rotayı eklerken Multer middleware'ini kullanacağız.
import express from 'express';
const app = express();
app.post('/upload', upload.single('dosya'), (req, res) => {
if (!req.file) {
return res.status(400).send('Dosya yüklenemedi.');
}
res.send({ message: 'Dosya başarıyla yüklendi', filePath: req.file.path });
});
app.listen(3000, () => console.log('Sunucu 3000 portunda çalışıyor.'));
Burada upload.single('dosya') ifadesi, istemciden "dosya" anahtarıyla gelen tek bir dosyayı beklediğimizi belirtir. Eğer yükleme başarılı olursa, dosya bilgileri req.file nesnesi içerisinde yer alacaktır.
Dosya Yükleme Yöntemleri Karşılaştırması
Dosya yükleme işlemlerinde farklı yaklaşımlar mevcuttur. İhtiyacınıza göre en uygun yöntemi seçmek için aşağıdaki tabloyu inceleyebilirsiniz.
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Disk Storage | Basit ve hızlıdır. | Sunucu diskini doldurur. |
| Memory Storage | Hızlıdır, dosyayı bellekte tutar. | Büyük dosyalarda RAM tüketir. |
| Cloud (S3 vb.) | Ölçeklenebilirdir. | Ekstra maliyet ve yapılandırma gerektirir. |
Güvenlik Önlemleri ve Dosya Filtreleme
Dosya yükleme servislerinde en büyük risk, kötü niyetli kullanıcıların sunucuya çalıştırılabilir dosyalar (örneğin .php, .exe veya .sh) yüklemesidir. Bu durumu engellemek için mutlaka dosya türü filtrelemesi (file filtering) yapmalısınız.
const fileFilter = (req, file, cb) => {
const izinVerilenTipler = ['image/jpeg', 'image/png', 'image/webp'];
if (izinVerilenTipler.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Sadece resim dosyaları yüklenebilir!'), false);
}
};
const upload = multer({ storage, fileFilter, limits: { fileSize: 2 * 1024 * 1024 } });
Bu kod bloğu, fileFilter ile sadece resim dosyalarına izin verirken, limits özelliği ile dosya boyutunu 2 MB ile kısıtlar. Bu, sunucunuzu hem gereksiz dosya kalabalığından hem de potansiyel DoS (Denial of Service) saldırılarından korur.
Kritik Güvenlik Uyarısı: Yüklenen dosyaları asla kullanıcıların erişebileceği dizinlerde doğrudan çalıştırmayın. Dosya isimlerini her zaman sunucu tarafında yeniden oluşturun ve orijinal isimleri veritabanında saklayın. Dosya yükleme dizininin dizin listeleme (directory listing) özelliğinin kapalı olduğundan emin olun.
Dosya Yükleme Servisini Test Etme
Servisinizi test etmek için Postman veya cURL kullanabilirsiniz. Aşağıdaki cURL komutu ile terminal üzerinden dosya yükleme işlemini simüle edebilirsiniz.
curl -X POST http://localhost:3000/upload \
-F "dosya=@/yol/resim.jpg"
Eğer her şey doğru yapılandırıldıysa, sunucunuzdan 200 OK yanıtı ve dosyanın yüklendiği dizin bilgisi dönecektir. Hata durumunda Multer tarafından döndürülen hata mesajlarını kontrol ederek debug sürecini hızlandırabilirsiniz.
Sıkça Sorulan Sorular
Multer ile çoklu dosya yüklemesi nasıl yapılır?
upload.single() yerine upload.array('dosyalar', 5) kullanarak aynı anda birden fazla dosya yükleyebilirsiniz. Burada 5 sayısı, aynı anda yüklenebilecek maksimum dosya sayısını belirtir.
Yüklenen dosyaları veritabanında nasıl tutmalıyım?
Dosyaların kendisini veritabanına (BLOB olarak) kaydetmek yerine, dosyayı bir depolama birimine (disk veya bulut) kaydedip, veritabanında sadece dosyanın yolunu (path) veya URL'ini saklamak en iyi pratiktir.
Dosya isimlerindeki karakter sorunlarını nasıl çözerim?
Dosya isimlerini her zaman sunucu tarafında rastgele bir hash veya benzersiz bir ID ile yeniden adlandırın. Orijinal dosya ismini veritabanında ayrı bir sütunda tutmak, karakter sorunlarını tamamen ortadan kaldırır.
Yükleme sırasında "MulterError: Unexpected field" hatası alıyorum, neden?
Bu hata, istemciden gönderilen form verisindeki anahtar adı ile sunucuda beklediğiniz anahtar adının (örneğin upload.single('dosya') içindeki 'dosya') eşleşmemesinden kaynaklanır.
Dosya yükleme servisi üretim (production) ortamında nasıl korunur?
Üretim ortamında dosyaları doğrudan sunucuda tutmak yerine AWS S3, Google Cloud Storage veya Azure Blob Storage gibi servisleri kullanın. Bu, sunucunuzun ölçeklenmesini kolaylaştırır ve güvenlik risklerini minimize eder.
Dosya Yükleme Servislerinde Performans Optimizasyonu
Dosya yükleme servisleri, özellikle yüksek trafikli uygulamalarda sunucu kaynaklarını (CPU ve RAM) yoğun bir şekilde tüketebilir. Kullanıcıların aynı anda büyük dosyalar yüklemesi, I/O darboğazlarına ve sunucunun yanıt veremez hale gelmesine neden olabilir. Bu durumu yönetmek için aşağıdaki stratejileri uygulayabilirsiniz:
Akış Tabanlı (Stream) İşleme
Dosyaları bellekte tutmak yerine doğrudan bir akış (stream) olarak dosya sistemine veya bulut depolama birimine yazmak, bellek kullanımını minimize eder. Multer, varsayılan olarak dosyaları diskte geçici olarak tutsa da, büyük dosyalar için limits parametresini kullanarak bellek sınırlarını kontrol altında tutmalısınız.
const upload = multer({
limits: {
fileSize: 10 * 1024 * 1024, // 10MB sınır
files: 5 // Aynı anda maksimum 5 dosya
}
});
İçerik Dağıtım Ağları (CDN) Kullanımı
Yüklenen dosyaları doğrudan Node.js sunucunuz üzerinden servis etmek, statik dosya sunumu nedeniyle ana uygulama mantığınızı yavaşlatabilir. Bunun yerine, yüklenen dosyaları bir nesne depolama servisine (AWS S3, Google Cloud Storage) gönderip, bu dosyaları bir CDN (CloudFront, Cloudflare) üzerinden servis etmek, sunucu üzerindeki yükü %80 oranında azaltacaktır.
Dosya Yükleme Süreçlerinde Hata Ayıklama (Debugging)
Dosya yükleme işlemleri sırasında karşılaşılan hatalar genellikle konfigürasyon eksikliklerinden veya izin sorunlarından kaynaklanır. Hataları daha hızlı tespit etmek için merkezi bir hata yakalama mekanizması kurmalısınız.
Özel Hata Yönetimi Middleware'i
Multer hatalarını standart Express hata yakalayıcılarınızdan ayırmak, istemciye daha anlamlı hata mesajları dönmenizi sağlar. Aşağıdaki örnek, dosya boyutu aşıldığında veya geçersiz dosya türü gönderildiğinde tetiklenen bir hata yakalayıcıyı göstermektedir:
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(400).json({ error: 'Dosya boyutu çok büyük (Maks 10MB).' });
}
return res.status(400).json({ error: err.message });
}
if (err) {
return res.status(500).json({ error: 'Sunucu hatası: ' + err.message });
}
next();
});
Dosya Sistemi İzinlerini Kontrol Etme
Linux tabanlı sunucularda en sık karşılaşılan hata EACCES: permission denied hatasıdır. Node.js sürecinin, yükleme yapılan dizine yazma izni olduğundan emin olmalısınız. Geliştirme aşamasında şu komutla dizin izinlerini doğrulayabilirsiniz:
# Yükleme klasörüne yazma izni verin
chmod -R 755 ./uploads
# Klasörün sahibini Node.js'i çalıştıran kullanıcı yapın
chown -R nodeuser:nodeuser ./uploads
İleri Seviye: Dosya İşleme (Image Processing)
Kullanıcıların yüklediği görselleri olduğu gibi saklamak yerine, sharp gibi kütüphaneler kullanarak görselleri sunucu tarafında yeniden boyutlandırmak ve optimize etmek, hem depolama alanından tasarruf sağlar hem de web sayfanızın yüklenme hızını artırır.
const sharp = require('sharp');
// Görseli yükledikten sonra yeniden boyutlandırma örneği
const processImage = async (filePath) => {
await sharp(filePath)
.resize(800, 800)
.jpeg({ quality: 80 })
.toFile(filePath.replace('.jpg', '_optimized.jpg'));
};
Sonuç
Node.js ile dosya yükleme servisi geliştirmek, doğru middleware kullanımı ve güvenlik filtrelemeleriyle oldukça güvenli hale getirilebilir. Bu rehberde, Multer kütüphanesini kullanarak dosyaları nasıl yöneteceğinizi, dosya türlerini nasıl kısıtlayacağınızı ve temel güvenlik önlemlerini nasıl alacağınızı öğrendiniz. Bir sonraki adım olarak, yüklenen dosyaları AWS S3 gibi bir bulut depolama servisine aktarmayı veya yüklenen resimleri otomatik olarak yeniden boyutlandıran bir "image processing" katmanı eklemeyi deneyebilirsiniz.
Yasal Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Uygulamanızda kullanmadan önce güvenlik açıklarını (özellikle dosya yükleme dizin izinleri) kendi mimarinize göre mutlaka gözden geçirin. Yazılım güvenliği, sürekli güncellenmesi gereken bir süreçtir.


Yorumlar (0)
Yorum Yaz