2012-09-05 7 views
26

Heroku'da barındırılan bir Rails uygulamasına sahibim. Uygulama Amazon S3'te PDF dosyaları oluşturur ve saklar. Kullanıcılar bu dosyaları tarayıcılarında görüntülemek veya bilgisayarlarına kaydetmek için indirebilirler.Raylar: gerçek S3 URL'sini kullanıcıya göstermeden S3'te saklanan dosyaların indirilmesine izin ver

Yapmakta olduğum sorun şu ki, bu dosyaların indirilmesi S3 URL'si aracılığıyla mümkün olsa da ("https://s3.amazonaws.com/my-bucket/F4D8CESSDF.pdf" gibi), açıkçası bir Bunu yapmanın iyi yolu. Kullanıcıya, arka uç ile ilgili çok fazla bilgi açığa çıkmak, ortaya çıkan güvenlik sorunlarından bahsetmek istemez.

Uygulamamın bir denetleyicideki dosya verilerini bir şekilde S3'ten almasını sağlayın, ardından kullanıcı için bir indirme akışı oluşturun, böylece Amazon URL'si açıkta kalmıyor mu?

+0

Açıkçası indirebilirsiniz ve sonra kullanıcıya geri akışa ama özellikle hızlı olmayacaktır. –

cevap

9

Evet, bu mümkündür - uzak dosyayı Rails ile getirip geçici olarak sunucunuzda saklayın veya doğrudan arabelleğe gönderin. Bununla ilgili problem, öncelikle kullanıcıya sunmadan önce dosyayı getirmeniz gerektiğidir.

#environment.rb 
require 'open-uri' 

#controller 
def index 
    data = open(params[:file]) 
    send_data data, :filename => params[:name], ... 
end 

This issue is also somewhat related: Bir tartışma için this thread bakınız, onların çözüm böyle bir şeydir.

+0

Bu basit çıktı, teşekkürler. Bu benim gerçek uygulama: def indir dosya_name = params ["file_id"] + ".pdf" data = open ("https://s3.amazonaws.com/#{ENV['S3_BUCKET_NAME']}/ # {dosya_adı} ") send_data data.read,: filename => file_name,: type =>" application/pdf ",: disposition => 'attachment', : stream => 'true',: buffer_size => ' 4096 ' end Bu problemin çözümü olarak çözümünüzü kabul ettim çünkü uygulamak en basit olanı. – futureshocked

+0

Serge'in de iyi olanı, Rails uygulamasını indirme işleminden kurtarmanın yararı ile, çalışmasını sağlamak için biraz daha fazla çalışmaya ihtiyaç duyuyor. – futureshocked

+0

Sadece diğerleri biliyorum, bulduğum iki konu var: 1) Sunucuya ve daha sonra kullanıcıya indirilebilen bir süre; ve 2) Kullanıcı deneyimi bekledikleri şey değildir. Tarayıcılarında bir indirme yapmak yerine, bir şey yüklüyor gibi görünüyor. Daha fazla tartışma için http://stackoverflow.com/a/23161355/293280 adresine bakın. –

51

S3 nesnelerini özel olarak oluşturabilir ve bunlar için url_for yöntemiyle (aws-s3 gem) geçici ortak URL'ler oluşturabilirsiniz. Bu sayede, uygulama sunucularınız aracılığıyla dosyaları daha ölçeklendiremezsiniz. Ayrıca, oturum tabanlı yetkilendirmeyi (örneğin uygulamanızda düzenleme), indirme olaylarının takibini vb. Sağlar.

Bunu yapmak için, s3 tarafından barındırılan dosyalara doğrudan bağlantıları geçici url oluşturan denetleyiciye/eyleme giden bağlantılara dönüştürün. ona yönlendirir. Şunun gibi: indir URL'ler içinde amazon etki alanının

class HostedFilesController < ApplicationController 

    def show 
    s3_name = params[:id] # sanitize name here, restrict access to only some paths, etc 
    AWS::S3::Base.establish_connection!(...) 
    url = AWS::S3::S3Object.url_for(s3_name, YOUR_BUCKET, :expires_in => 2.minutes) 
    redirect_to url 
    end 

end 

Gizleme genellikle DNS aliasing ile yapılır. create CNAME record aliasing your subdomain, ör. downloads.mydomain, s3.amazonaws.com. Daha sonra AWS::S3::Base.establish_connection!(:server => "downloads.mydomain", ...)'da :server seçeneğini belirtebilirsiniz ve S3 mücevher bağlantı oluşturmak için kullanacaktır.

+0

Serge, yöntemini denedim. Çalışır, ancak URL şöyle görünür: http://s3.amazonaws.com/my-bucket/F4D8CED0.pdf?AWSAccessKeyId=my-actual-key&Expires=1346904098&Signature=Wo7wYH6Ek%2FBot3wd2xYbGt4ybSU%3D. İdeal olarak görmek istediğim, amazon'dan bahsetmez, ama "http://mydomain.com/download/file.pdf. Bu mümkün mü? – futureshocked

+0

CNAME ile buna oldukça yakın olabilirsiniz, ancak daha çok "birşey.mydomain.com/path/file.pdf" gibi olacaktır. Bunu yansıtmak için cevabı güncelledim. –

+0

Çok hoş bir çözüm, teşekkürler Serge. – futureshocked

-1

İlk olarak, etki alanınızda here açıklamasını yapmak istediğiniz bir CNAME oluşturmanız gerekir.

İkinci olarak, CNAME'ye koyduğunuz aynı ada sahip bir kova oluşturmanız gerekir.

Ve siz yapılandırma/başlatıcıları/carrierwave.rb bu yapılandırmaları eklemek gerek bitirmek için:

CarrierWave.configure do |config| 
    ... 
    config.asset_host   = 'http://bucket_name.your_domain.com' 
    config.fog_directory  = 'bucket_name.your_domain.com' 
    ... 
end