R.Reddington

WFN Üye
Konular
562
Mesajlar
562
Çözüm
0
Ticaret Puanı
0
Üyelik
24 Gün
Konum
Kastamonu
Web Sitesi
Var
Alanı
Sosyal Backlink
1/1
Konu sahibi
İndirilebilir bir dosya sunmak için Rails’te en pratik yöntem, bir controller action içinde send_file kullanıp bu action’a bir rota tanımlamaktır. Dosya uygulamanın storage veya public altında tutuluyorsa, indirme bağlantısı bu rotaya yönlendirilir; istek geldiğinde Rails dosyayı HTTP yanıtı olarak gönderir.

Controller içinde dosya indirme action’ı oluşturma​


Örneğin storage/downloads/rapor.pdf konumunda bulunan bir dosyayı indirmek için ilgili controller’a şu action’ı ekleyin:

Ruby:
class DownloadsController < ApplicationController
  def report
    file_path = Rails.root.join("storage", "downloads", "rapor.pdf")

    unless File.file?(file_path)
      head :not_found
      return
    end

    send_file file_path,
              filename: "rapor.pdf",
              type: "application/pdf",
              disposition: "attachment"
  end
end

Burada Rails.root, uygulamanızın ana dizinini gösterir. File.file? kontrolü dosyanın gerçekten mevcut ve dosya türünde olup olmadığını denetler. Dosya bulunamazsa 404 Not Found yanıtı gönderilir; bu, indirme işleminin başarısız olduğu anlamına gelir, ancak dosya yolunun dışarıya sızdığı anlamına gelmez.

disposition: "attachment" tarayıcıya içeriği sayfada göstermeye çalışmak yerine indirme olarak ele almasını söyler. filename kullanıcının indireceği dosyanın adını, type ise dosyanın MIME türünü belirler.

Action için rota tanımlama​


config/routes.rb dosyasına controller action’ını çağıran bir rota ekleyin:

Ruby:
Rails.application.routes.draw do
  get "downloads/report", to: "downloads#report", as: :download_report
end

Bu tanımdan sonra download_report_path yardımcı metodu oluşur. Uygulama çalışırken tarayıcıdan /downloads/report adresine gidildiğinde Rails, DownloadsController#report action’ını çalıştırır ve dosyayı gönderir.

Bir görünümde indirme bağlantısı vermek için:

Kod:
<%= link_to "Raporu indir", download_report_path %>

Dosya mevcutsa tarayıcı indirme işlemini başlatır. Dosya yoksa controller’ın head :not_found satırı nedeniyle 404 yanıtı alırsınız. Bu durumda önce beklenen dosyanın gerçekten storage/downloads/rapor.pdf altında bulunduğunu ve uygulamanın çalıştığı ortamda erişilebilir olduğunu kontrol edin.

Dosyayı tarayıcıda göstermek yerine indirme olarak sunma​


PDF veya görsel gibi bazı dosya türleri tarayıcıda açılabilir. Kullanıcıya indirme penceresi göstermek istiyorsanız disposition: "attachment" kullanın. Dosyanın tarayıcıda açılmasına izin vermek istiyorsanız bu değeri inline yapabilirsiniz:

Ruby:
send_file file_path,
          filename: "rapor.pdf",
          type: "application/pdf",
          disposition: "inline"

inline kullanılması dosyanın kesin olarak gösterileceğini garanti etmez; sonuç tarayıcının ve dosya türünün desteklenmesine bağlıdır. Kesin indirme davranışı için attachment tercih edilir.

Bellekte oluşturulan içeriği indirme​


Dosya diskte hazır değilse veya içerik istek sırasında oluşturuluyorsa send_data kullanabilirsiniz. Örneğin varsayımsal bir CSV çıktısı şu şekilde gönderilebilir:

Ruby:
def users_csv
  csv_content = User.order(:id).pluck(:id, :email).map do |id, email|
    "#{id},#{email}"
  end.join("\n")

  send_data csv_content,
            filename: "kullanicilar.csv",
            type: "text/csv",
            disposition: "attachment"
end

Bu yöntemde send_data dosya yolu değil, bellekteki metin veya ikili veriyi yanıt olarak gönderir. Büyük dosyaları tamamen bellekte oluşturmak RAM kullanımını artırabileceği için bu yaklaşım küçük ve orta boyutlu çıktılarda daha uygundur. Büyük veya önceden oluşturulmuş dosyalarda send_file kullanmak daha doğru bir seçimdir.
İhtiyaçKullanılacak yöntemTemel fark
Diskte bulunan dosyayı göndermeksend_fileDosya yolundan yanıt üretir
Bellekte oluşturulan içeriği göndermeksend_dataMetin veya ikili veriyi doğrudan gönderir
Herkese açık sabit dosyaDoğrudan statik dosya bağlantısıController yetkilendirmesi çalışmaz
Bu ayrım önemlidir: Dosyanın yalnızca oturum açmış veya belirli yetkiye sahip kullanıcılar tarafından indirilmesi gerekiyorsa doğrudan public dizinine bağlantı vermek yerine controller action’ı kullanın. Controller içinde yetki kontrolünü send_file çağrısından önce yapın.

Yetkili kullanıcılar için güvenli indirme​


Örneğin yalnızca oturum açmış kullanıcıların dosya indirebildiği basit bir action şöyle olabilir:

Ruby:
def private_report
  return head :unauthorized unless current_user

  file_path = Rails.root.join("storage", "reports", "rapor.pdf")

  return head :not_found unless File.file?(file_path)

  send_file file_path,
            filename: "rapor.pdf",
            type: "application/pdf",
            disposition: "attachment"
end

Gerçek uygulamada yetki koşulunu uygulamanızın kimlik doğrulama ve yetkilendirme yapısına göre kurun. Kullanıcıdan gelen dosya adını doğrudan Rails.root.join içine eklemeyin; ../ gibi yol parçaları, uygulama dışındaki dosyalara erişim riski oluşturabilir. Kullanıcı seçimi gerekiyorsa veritabanındaki güvenilir bir kayıtla dosya eşleştirin veya izin verilen dosya adlarını sınırlı bir listeyle doğrulayın.

İndirme bağlantısına tıkladığınızda beklenen dosya adıyla indirme başlaması, action’ın çalıştığını ve yanıt başlıklarının uygun olduğunu gösterir. 404 yanıtı dosyanın beklenen konumda bulunmadığını; 401 veya 403 yanıtı ise kimlik ya da yetki kontrolünün isteği reddettiğini gösterir. Bu sonuçlar tek başına dosyanın bozuk olduğunu kanıtlamaz. Dosya indirildiği hâlde açılamıyorsa gerçek dosya türünü, type değerini ve dosyanın eksik veya sıfır boyutlu olup olmadığını ayrıca kontrol edin.
 

Sende şimdi bize katılmak ister misin?

Kayıt ol

Bize katılım kolay ve ücretsizdir!

Foruma git ?

Bu konuyu görüntüleyen kullanıcılar

Bu konuyu şu anda görüntüleyen üye bulunmuyor.
Robotlar:
  • Anthropic