Rails: разрешить загрузку файлов, хранящихся на S3, без отображения фактического URL-адреса S3 для пользователя
У меня есть приложение Rails, размещенное на Heroku. Приложение создает и сохраняет файлы PDF на Amazon S3. Пользователи могут загружать эти файлы для просмотра в своем браузере или для сохранения на своем компьютере.
Проблема заключается в том, что, хотя загрузка этих файлов возможна через URL-адрес S3 (например, "https://s3.amazonaws.com/my-bucket/F4D8CESSDF.pdf" ), это, очевидно, НЕ является хорошим способ сделать это. Нежелательно предоставлять пользователю столько информации о бэкэнд, не говоря уже о проблемах безопасности, которые возникают.
Возможно ли, чтобы мое приложение каким-то образом извлекло данные файла из S3 в контроллере, а затем создало поток загрузки для пользователя, чтобы URL-адрес Amazon не был открыт?
Ответы
Ответ 1
Да, это возможно - просто извлеките удаленный файл с помощью Rails и временно сохраните его на своем сервере или отправьте его непосредственно из буфера. Проблема с этим - это, конечно, тот факт, что вам нужно сначала извлечь файл, прежде чем вы сможете его обслужить. См. этот поток для обсуждения, их решение выглядит примерно так:
#environment.rb
require 'open-uri'
#controller
def index
data = open(params[:file])
send_data data, :filename => params[:name], ...
end
Эта проблема также несколько связана.
Ответ 2
Вы можете создавать свои s3-объекты как частные и генерировать временные общедоступные URL-адреса для них с помощью url_for метода (aws-s3 gem). Таким образом, вы не передаете файлы через свои серверы приложений, которые более масштабируемы. Он также позволяет размещать авторизацию на основе сеанса (например, разрабатывать в вашем приложении), отслеживать события загрузки и т.д.
Чтобы сделать это, измените прямые ссылки на s3 размещенные файлы в ссылки на контроллер/действие, которое создает временный url и перенаправляет на него. Вот так:
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
Скрытие домена амазонки в URL-адресах загрузки обычно выполняется с использованием псевдонимов DNS. Вам нужно создать запись CNAME, наложенную на ваш поддомен, например. downloads.mydomain
, до s3.amazonaws.com
. Затем вы можете указать опцию :server
в AWS::S3::Base.establish_connection!(:server => "downloads.mydomain", ...)
, а камень S3 будет использовать ее для генерации ссылок.
Ответ 3
Сначала вам нужно создать CNAME в своем домене, например, объяснить здесь.
Во-вторых, вам нужно создать ведро с тем же именем, которое вы поместили в CNAME.
И для завершения вам нужно добавить эти конфигурации в свой config/initializers/carrierwave.rb:
CarrierWave.configure do |config|
...
config.asset_host = 'http://bucket_name.your_domain.com'
config.fog_directory = 'bucket_name.your_domain.com'
...
end