Node.js İle Multer Kullanarak Çoklu Dosya Yükleme Servisi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Çalışmaya başlamadan önce bilgisayarınızda güncel bir Node.js sürümünün (LTS 22 veya üzeri önerilir) kurulu olması gerekmektedir. Projenizi başlatmak ve gerekli bağımlılıkları yüklemek için terminalinizde aşağıdaki komutları izleyin.

# Proje klasörünü oluşturun ve içine girin
mkdir node-file-upload-service
cd node-file-upload-service

# Projeyi başlatın
npm init -y

# Gerekli paketleri kurun
npm install express multer

Bu komutlar, projenizin temelini atar ve Express ile Multer kütüphanelerini projenize dahil eder. express, sunucu tarafında HTTP isteklerini yönetmemizi sağlar; multer ise multipart/form-data türündeki verileri işlemek için kullanılır.

Multer Yapılandırması ve Disk Depolama

Dosyaları sunucuda nereye ve hangi isimle kaydedeceğimizi belirlemek için Multer'ın diskStorage motorunu kullanmalıyız. Bu, dosyaların rastgele isimlerle değil, belirli bir düzenle kaydedilmesini sağlar.

const multer = require('multer');
const path = require('path');

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/'); // Dosyaların kaydedileceği klasör
  },
  filename: (req, file, cb) => {
    // Dosya ismini benzersiz hale getirme
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({ storage: storage });

Burada destination fonksiyonu dosyanın fiziksel konumunu, filename fonksiyonu ise çakışmaları önlemek için benzersiz isim oluşturma mantığını belirler. path.extname kullanımı, orijinal dosya uzantısını korumamıza olanak tanır.

Çoklu Dosya Yükleme Servisi Kodlama

Multer ile birden fazla dosyayı aynı anda kabul etmek için upload.array() metodunu kullanırız. Bu metod, formdan gelen "files" isimli alanı dinleyerek dizi şeklinde işler.

const express = require('express');
const app = express();

// Çoklu yükleme rotası
app.post('/upload-multiple', upload.array('files', 5), (req, res) => {
  if (!req.files || req.files.length === 0) {
    return res.status(400).send('Dosya yüklenmedi.');
  }
  res.send({ message: 'Dosyalar başarıyla yüklendi!', files: req.files });
});

app.listen(3000, () => console.log('Sunucu 3000 portunda çalışıyor.'));

upload.array('files', 5) ifadesindeki '5' rakamı, kullanıcının tek seferde en fazla 5 dosya yükleyebileceği anlamına gelir. Bu, sunucu kaynaklarını korumak için kritik bir sınırlamadır.

Dosya Türü ve Boyut Kısıtlamaları

Güvenlik ve performans açısından, yüklenen dosyaların türünü ve boyutunu kontrol etmek zorunludur. Multer, fileFilter ve limits seçenekleri ile bu kontrolü sağlar.

const upload = multer({
  storage: storage,
  limits: { fileSize: 2 * 1024 * 1024 }, // Maksimum 2MB
  fileFilter: (req, file, cb) => {
    const allowedTypes = /jpeg|jpg|png|pdf/;
    const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
    if (extname) return cb(null, true);
    cb(new Error('Sadece resim veya PDF dosyaları yüklenebilir!'));
  }
});

Bu yapılandırma, sunucunuza zararlı olabilecek dosyaların (örneğin .exe veya .sh) yüklenmesini engeller. fileSize değeri bayt cinsinden hesaplanır.

Dosya Yükleme Yöntemlerinin Karşılaştırılması

Yöntem Avantajı Dezavantajı
Disk Storage Basit, hızlı erişim Sunucu diskini doldurabilir
Memory Storage Hızlı işleme, veritabanına aktarım RAM tüketimi yüksek
Cloud Storage Ölçeklenebilir, güvenli Ekstra maliyet ve gecikme
Güvenlik Uyarısı: Kullanıcı tarafından yüklenen dosyaları asla doğrudan çalıştırılabilir dizinlerde tutmayın. Dosya isimlerini mutlaka sistem tarafından yeniden adlandırın ve dosya içeriğini (MIME type) sunucu tarafında doğrulamadan veritabanına kaydetmeyin.

Hata Yönetimi ve Debug İpuçları

Multer hataları genellikle Express'in standart hata yakalayıcılarına düşer. Bu hataları yönetmek için özel bir middleware kullanmak kullanıcı deneyimini artırır.

app.use((err, req, res, next) => {
  if (err instanceof multer.MulterError) {
    return res.status(400).json({ error: err.message });
  }
  res.status(500).json({ error: 'Beklenmeyen bir hata oluştu.' });
});

Bu blok, Multer'dan kaynaklanan (örneğin dosya boyutu aşımı) hataları yakalar ve istemciye anlamlı bir mesaj dönmesini sağlar.

Sıkça Sorulan Sorular

Multer ile yüklenen dosyalar neden görünmüyor?

Dosyaların kaydedildiği klasörün (örneğin 'uploads/') sunucu tarafında statik olarak tanımlanması gerekir. app.use('/uploads', express.static('uploads')); satırını eklediğinizden emin olun.

Aynı anda hem dosya hem de metin verisi nasıl gönderilir?

Multer, multipart/form-data yapısı sayesinde metin alanlarını req.body içinde, dosyaları ise req.files içinde otomatik olarak ayrıştırır.

Dosya isimlerini nasıl veritabanına kaydederim?

req.files dizisi içinde dönen dosya nesnelerindeki filename ve path özelliklerini alarak veritabanı sorgunuza (SQL veya NoSQL) ekleyebilirsiniz.

Dosya boyutu limitini nasıl aşabilirim?

Limitleri artırmak mümkündür ancak bu, sunucunuzun DoS (Denial of Service) saldırılarına açık hale gelmesine neden olabilir. Limitleri her zaman mantıklı sınırlar içinde tutun.

Cloudinary veya AWS S3 kullanabilir miyim?

Evet, Multer'ı doğrudan S3 ile kullanmak için multer-s3 kütüphanesini tercih etmelisiniz. Bu, dosyaları yerel disk yerine doğrudan bulut depolama birimine gönderir.

Sorumluluk Reddi: Bu rehberde paylaşılan kodlar eğitim amaçlıdır. Üretim ortamında dosya yükleme servisleri için mutlaka ek güvenlik katmanları (antivirüs taraması, dosya içeriği doğrulaması, rate limiting) eklenmelidir.

Dosya Yükleme Servislerinde Performans Optimizasyonu

Çoklu dosya yükleme işlemleri, özellikle büyük boyutlu görseller veya videolar söz konusu olduğunda sunucu kaynaklarını hızla tüketebilir. Performansı artırmak ve sunucunuzun yanıt süresini optimize etmek için şu stratejileri uygulayabilirsiniz:

  • Dosya Sıkıştırma: Sunucuya yüklenen görselleri işlemek için sharp gibi kütüphaneler kullanarak yükleme anında yeniden boyutlandırma ve sıkıştırma yapın.
  • Stream Kullanımı: Büyük dosyaları belleğe (RAM) almak yerine doğrudan akış (stream) yöntemiyle diske veya buluta yazın.
  • Asenkron İşleme: Dosya yüklendikten sonra yapılacak ağır işlemleri (örneğin veritabanı kaydı veya e-posta bildirimi) bir kuyruk mekanizması (Redis/BullMQ) ile arka plana atın.

Yükleme Servisleri İçin İleri Düzey Güvenlik Önlemleri

Multer ile gelen varsayılan ayarlar, üretim ortamında tek başına yeterli değildir. Kötü niyetli kullanıcıların sunucunuza zararlı yazılım yüklemesini engellemek için şu katmanları eklemelisiniz:

1. Dosya İçeriği (MIME Type) Doğrulaması

Dosya uzantısına güvenmek yerine, dosyanın gerçek içeriğini kontrol eden file-type gibi kütüphaneler kullanın. Bir saldırgan .exe dosyasının adını .jpg yaparak yüklemeye çalışabilir.

const FileType = require('file-type');

const validateFile = async (filePath) => {
    const type = await FileType.fromFile(filePath);
    const allowed = ['image/jpeg', 'image/png'];
    if (!type || !allowed.includes(type.mime)) {
        throw new Error('Geçersiz dosya içeriği!');
    }
    return true;
};

2. Dosya İsimlerinin Rastgeleleştirilmesi

Kullanıcının yüklediği orijinal dosya ismini asla doğrudan kullanmayın. Bu durum "Directory Traversal" saldırılarına yol açabilir. Bunun yerine crypto veya uuid kullanarak benzersiz isimler oluşturun:

const crypto = require('crypto');
const path = require('path');

const storage = multer.diskStorage({
    destination: './uploads/',
    filename: (req, file, cb) => {
        const randomName = crypto.randomBytes(16).toString('hex');
        cb(null, `${randomName}${path.extname(file.originalname)}`);
    }
});

3. Rate Limiting (İstek Sınırlandırma)

Bir kullanıcının kısa sürede binlerce dosya yükleyerek sunucunuzu "Denial of Service" (DoS) saldırısına maruz bırakmasını engellemek için express-rate-limit kullanın.

const rateLimit = require('express-rate-limit');

const uploadLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 dakika
    max: 10, // Her IP için maksimum 10 yükleme isteği
    message: 'Çok fazla yükleme isteği gönderdiniz, lütfen bekleyin.'
});

app.post('/upload', uploadLimiter, upload.array('files'), (req, res) => {
    res.send('Dosyalar başarıyla yüklendi.');
});
Profesyonel İpucu: Üretim ortamında dosyaları doğrudan Node.js sunucunuzun dosya sistemine yazmak yerine, dosyaları bir Nginx veya CDN arkasında tutmak, statik dosya sunum hızınızı ciddi oranda artıracaktır.

Sonuç

Node.js ve Multer kullanarak çoklu dosya yükleme servisi oluşturmak, doğru yapılandırma ile oldukça verimli bir süreçtir. Bu rehberde; disk üzerinde depolama, dosya kısıtlamaları, hata yönetimi ve güvenlik önlemleri gibi temel adımları tamamladık. Bir sonraki adım olarak, yüklenen dosyaları AWS S3 veya Google Cloud Storage gibi bulut tabanlı bir sisteme aktarmayı deneyerek uygulamanızı ölçeklenebilir hale getirebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Emre Yılmaz

Bilgi odaklı nasıl yapılır içerikleriyle karmaşık süreçleri herkes için anlaşılır kılıyorum. Okuyucularımın zamanını verimli kullanmalarını sağlayan stratejiler geliştiriyorum.

Yorumlar (0)

Yorum Yaz