YAZILIM

DigitalOcean Spaces ile Dosya ve Medya Depolama

DigitalOcean Spaces ile Dosya ve Medya Depolama yazısının kapak görseli

Bir uygulama büyüdükçe kullanıcı yüklemeleri, profil fotoğrafları, video dosyaları ya da yedekler gibi verilerin saklanacağı bir yer gerekiyor. Bu dosyaları doğrudan Droplet’in diskinde tutmak küçük projelerde işe yarasa da, disk alanı büyüdükçe ve sunucu sayısı arttıkça sürdürülebilir bir çözüm olmaktan çıkıyor. DigitalOcean’ın Spaces ürünü, tam olarak bu ihtiyaç için tasarlanmış bir nesne depolama (object storage) hizmeti. Bu yazıda Spaces’in ne olduğunu, bir bucket’ın nasıl oluşturulduğunu ve bir Node.js uygulamasından dosyaların nasıl yüklenip servis edildiğini adım adım anlatıyorum.

Spaces Nedir, Ne Zaman İşe Yarar

Spaces, Amazon S3 ile uyumlu bir API sunan nesne depolama hizmeti. Bu uyumluluk sayesinde S3 için yazılmış araçların, kütüphanelerin ve entegrasyonların büyük bölümü herhangi bir değişiklik yapılmadan Spaces üzerinde de çalışabiliyor. Depolanan her dosya bir “bucket” içinde tutuluyor ve bu bucket’lara built-in bir CDN üzerinden dünya genelinde hızlı erişim sağlanabiliyor.

Kullanıcı yüklemeleri, statik site varlıkları (görsel, CSS, JavaScript dosyaları), veritabanı yedekleri, log arşivleri ya da bir CMS’in medya kütüphanesi gibi büyük hacimli ve sık erişilen verilerin saklanması için Spaces oldukça uygun bir seçenek. Bir Droplet’in diskini bu tür verilerle şişirmek yerine, dosyaları ayrı ve ölçeklenebilir bir katmanda tutmak uzun vadede hem yönetimi kolaylaştırıyor hem de sunucu performansını koruyor.

Adım 1: Bir Space Oluşturma

DigitalOcean panelinde sol menüden Spaces Object Storage sekmesine girip Create Space Bucket butonuna tıklanır. Karşına birkaç temel ayarın seçilmesi gereken bir ekran çıkar.

Bölge seçimi: Bucket’ın hangi veri merkezinde barındırılacağını belirler. Uygulamanın çalıştığı Droplet ya da App Platform kaynağıyla aynı bölgenin seçilmesi, veri transfer hızını artırır ve bazı durumlarda iç ağ üzerinden ücretsiz erişim sağlar.

Bucket adı: Bucket’a verilecek isim global olarak benzersiz olmalı, çünkü bu isim aynı zamanda erişim adresinin bir parçası oluyor.

CDN etkinleştirme: Spaces’e dahil olan CDN, statik dosyaların dünya genelindeki farklı sunuculardan hızlı bir şekilde servis edilmesini sağlıyor. Görsel ya da video gibi sık erişilen dosyalar için bu özelliğin açık bırakılması öneriliyor.

Ayarlar tamamlandıktan sonra Create Space butonuna tıklanarak bucket oluşturuluyor. İşlem birkaç saniye içinde tamamlanır.

Adım 2: Erişim Anahtarlarının Oluşturulması

Bir uygulamanın Spaces’e dosya yükleyebilmesi için bir erişim anahtarı (access key) ve gizli anahtar (secret key) çiftine ihtiyaç duyuluyor. Bu anahtarlar panelin API sekmesinde, Spaces Keys bölümünden oluşturuluyor. Generate New Key butonuna tıklanıp anahtara bir isim verildikten sonra hem access key hem de secret key oluşturuluyor.

Secret key sadece oluşturulduğu anda gösteriliyor, bu yüzden güvenli bir yere kaydedilmesi gerekiyor. Bu bilgiler de tıpkı veritabanı bağlantı bilgileri gibi bir .env dosyasında saklanmalı, koda doğrudan yazılmamalı:

SPACES_KEY=access_key_degeri
SPACES_SECRET=secret_key_degeri
SPACES_BUCKET=bucket_adi
SPACES_REGION=fra1
SPACES_ENDPOINT=fra1.digitaloceanspaces.com

Adım 3: Node.js Üzerinden Bağlantı Kurma

Spaces, S3 uyumlu olduğu için AWS SDK doğrudan kullanılabiliyor. Öncelikle gerekli paket kuruluyor:

npm install @aws-sdk/client-s3

Ardından bir bağlantı istemcisi oluşturuluyor:

const { S3Client } = require('@aws-sdk/client-s3');
require('dotenv').config();

const s3 = new S3Client({
  endpoint: `https://${process.env.SPACES_ENDPOINT}`,
  region: process.env.SPACES_REGION,
  credentials: {
    accessKeyId: process.env.SPACES_KEY,
    secretAccessKey: process.env.SPACES_SECRET,
  },
});

module.exports = s3;

Adım 4: Dosya Yükleme

Bir dosyanın Spaces’e yüklenmesi PutObjectCommand üzerinden yapılıyor. Aşağıdaki örnek, yerel bir dosyayı okuyup bucket’a yüklüyor:

const { PutObjectCommand } = require('@aws-sdk/client-s3');
const fs = require('fs');
const s3 = require('./lib/spaces');

async function uploadFile(localPath, remoteKey, contentType) {
  const fileStream = fs.createReadStream(localPath);

  const command = new PutObjectCommand({
    Bucket: process.env.SPACES_BUCKET,
    Key: remoteKey,
    Body: fileStream,
    ContentType: contentType,
    ACL: 'public-read',
  });

  return s3.send(command);
}

uploadFile('./uploads/foto.jpg', 'kullanici-yuklemeleri/foto.jpg', 'image/jpeg')
  .then(() => console.log('Yükleme tamamlandı'))
  .catch((err) => console.error('Yükleme hatası:', err.message));

ACL alanı dosyanın erişim iznini belirliyor. public-read seçildiğinde dosya, doğrudan bir bağlantı üzerinden herkese açık şekilde erişilebilir hale geliyor. Hassas dosyalar için private seçilip, gerektiğinde geçici erişim bağlantıları (presigned URL) üzerinden paylaşım yapılabiliyor.

Adım 5: CDN Üzerinden Dosyaya Erişim

CDN etkinleştirilmiş bir bucket’a yüklenen dosyalar, şu formatta bir adres üzerinden erişilebilir hale geliyor:

https://bucket-adi.fra1.cdn.digitaloceanspaces.com/kullanici-yuklemeleri/foto.jpg

Bu adres doğrudan bir <img> etiketinde ya da bir API yanıtında kullanılabiliyor. CDN, dosyayı ilk istekte kaynak sunucudan çekip önbelleğe alıyor, sonraki istekler kullanıcıya coğrafi olarak en yakın CDN sunucusundan karşılanıyor.

Büyük Dosyalar İçin Multipart Upload

100 MB üzerindeki dosyalarda tek seferde yükleme yerine parçalı yükleme (multipart upload) kullanılması öneriliyor. Bu yöntem, büyük bir dosyayı küçük parçalara bölüp ayrı ayrı yüklüyor ve bir parçada sorun yaşanması durumunda sadece o parçanın yeniden gönderilmesine imkan tanıyor. AWS SDK’nın Upload sınıfı bu süreci otomatik olarak yönetiyor, geliştiricinin parçalama mantığını elle yazmasına gerek kalmıyor.

Sık Karşılaşılan Sorunlar

Yükleme sırasında erişim reddedildi hatası alınıyor: Genellikle access key ve secret key’in yanlış kopyalanmasından ya da anahtarın yetkisiz olmasından kaynaklanıyor. Panelden yeni bir anahtar çifti oluşturup tekrar denenmesi çoğu zaman sorunu çözüyor.

Yüklenen dosyaya tarayıcıdan erişilemiyor: Bu durum, dosyanın ACL ayarının private olarak kaldığı durumlarda ortaya çıkıyor. Herkese açık erişim gerekiyorsa yükleme sırasında public-read ACL’inin tanımlandığından emin olunmalı.

CORS hatası alınıyor: Bir frontend uygulaması doğrudan tarayıcıdan Spaces’e dosya yüklemeye çalıştığında CORS politikası engelleyebiliyor. Bucket ayarlarındaki Settings sekmesinden ilgili domain için CORS kuralı tanımlanması gerekiyor.

Sonraki Adımlar

Spaces artık uygulamaya bağlı ve dosya yükleme akışı çalışır durumda. Buradan sonra ömrü dolan dosyaları otomatik temizlemek için lifecycle kuralları tanımlanabilir, farklı ortamlar için ayrı bucket’lar oluşturulabilir ya da mevcut bir S3 tabanlı sistemden Spaces’e geçiş yapılabilir. Bir sonraki yazıda bir Droplet üzerine Docker kurup container tabanlı bir uygulamanın nasıl dağıtıldığı anlatılacak.

Kendi bucket’ını oluşturup denemek istersen, referans linkim üzerinden kayıt olarak bana destek olabilirsin.

Tüm projelerim ve üzerinde çalıştığım konuları incelemek istersen https://hub.barisgunduz.com/ adresini ziyaret edebilirsin.

Web ve mobil teknolojilere ilgi duyuyorum. Yaklaşık 14 yıldır web geliştirme ve internet reklamcılığı üzerinde çalışıyorum. Web yazılım teknolojileri ve yönetimi konusunda uzmanım. Birçok şirkete teknoloji ve reklamcılık danışmanlığı verdim. Hâlâ bazılarına destek vermeye devam ediyorum. Kendi projelerimle ilgili bazı çalışmalarım var. Çoğu içerik üreticiliği ile ilgili. Projelerimin hepsi Gündüz Medya markası altında toplanmıştır.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir