Dosya Yönetimi
Modül: src/modules/files
Upload altyapısı: src/utils/upload.js
Depolama: MinIO
Tüm dosyalar MinIO üzerinde saklanır. MinIO, Amazon S3 ile uyumlu açık kaynaklı bir nesne depolama sistemidir — API olarak S3 istemcisi kullanılır ama endpoint kendi sunucuna işaret eder.
Bağlantı Ayarları
upload.js dosyasında şu env değişkenleri kullanılır:
| Değişken | Açıklama | Varsayılan |
|---|---|---|
AWS_ENDPOINT |
MinIO sunucu adresi | localhost |
AWS_BUCKET_NAME |
Bucket adı | uploads |
AWS_ACCESS_KEY |
Erişim anahtarı | minioadmin |
AWS_SECRET_KEY |
Gizli anahtar | minioadmin |
BASE_URL |
Dosya URL'lerinde kullanılacak base URL | localhost:3000 |
DISABLE_BUCKET_CHECK |
true yapılırsa başlangıçta bucket kontrolü atlanır |
false |
Uygulama başlarken otomatik olarak bucket var mı kontrol eder, yoksa oluşturur.
URL Yapısı
Yüklenen her dosya şu URL formatıyla erişilebilir hale gelir:
https://{BASE_URL}/api/cdn/view/{dosya_adı}
Dosya adı {uniqueId}-{timestamp}.{uzantı} formatında üretilir.
Dosya Upload Akışı
- Multer ile dosya alınır (
memoryStorage— geçici olarak RAM'de tutulur) - Kullanıcının toplam depolama kullanımı hesaplanır
- 500MB limiti aşılacaksa hata fırlatılır
- MinIO'ya yüklenir
filestablosuna kayıt oluşturulur (status: 'PENDING')- PDF ise sayfa görsellerine dönüştürülür (her sayfa
filePagestablosuna eklenir) - Görsel dönüşüm başarılı olursa
status: 'PROCESSED', başarısız olursa'FAILED'yapılır
Tablolar
files
| Alan | Açıklama |
|---|---|
userId |
Dosyanın sahibi |
originalName |
Yüklenen orijinal dosya adı |
storageName |
MinIO'daki dosya adı (unique) |
url |
CDN erişim URL'si |
size |
Bayt cinsinden boyut |
mimeType |
Dosya MIME tipi |
folderId |
Klasör (opsiyonel) |
status |
PENDING, PROCESSED, FAILED |
filePages
PDF dosyaların sayfa görsellerini saklar. Her sayfa ayrı bir kayıt olarak tutulur.
| Alan | Açıklama |
|---|---|
fileId |
Bağlı olduğu dosya |
pageNumber |
Sayfa numarası (1'den başlar) |
originalImageUrl |
Sayfanın MinIO'daki görsel URL'si |
status |
PENDING, PROCESSED, FAILED |
fileFolders
Klasör yapısı. Self-referential (bir klasörün parent klasörü olabilir). Ayrıca categoryId ile kategori-klasör ayrımı yapılabilir.
Maarif Test Dosyaları
Maarif AI'dan üretilen testler de files tablosunda saklanır, ancak gerçek bir dosya değildir — JSON verisidir. Bu dosyalar özel bir MIME tipiyle işaretlenir:
application/x-maarif-test+json
storageName alanı virtual/maarif-test-{id}.json formatında tutulur. Bu "sanal" prefix, bu dosyaların MinIO'ya gerçekten yüklenmediğini belirtir.
Metadata alanında şunlar saklanır:
{
"kind": "maarif_test",
"questionBankId": "...",
"lessonId": "...",
"gradeLabel": "...",
"topic": "...",
"difficulty": "Orta",
"questionCount": 20,
"source": "maarif_ai"
}
PDF → Görsel Dönüşümü
PDF yüklendiğinde aiProcessor.convertPdfToImages() çağrılır. Bu fonksiyon PDF'in her sayfasını ayrı bir görsel olarak MinIO'ya yükler ve filePages tablosuna kaydeder.
Bu sayfa görselleri iki amaçla kullanılır:
- AI Öğretmen — Öğrencinin yüklediği PDF'i sayfa sayfa görsele çevirerek Gemini'ye gönderir
- Soru bankası işleme — Yüklenen soru PDF'ini görselleştirerek n8n LaTeX çıkarıcıya gönderir
500MB Kullanıcı Limiti
Her upload öncesinde şu kontrol yapılır:
const totalSize = await db.files.sum('size', { where: { userId: user.id } });
const limit = 500 * 1024 * 1024; // 500MB
if ((totalSize || 0) + file.size > limit) {
throw new ApiError(400, 'Storage limit exceeded');
}
Silinen dosyalar paranoid: false değil, gerçekten silinir — soft delete yok. Dolayısıyla silinmiş dosyalar limite dahil değildir.