Подтвердить что ты не робот

Rails: разрешить загрузку файлов, хранящихся на S3, без отображения фактического URL-адреса S3 для пользователя

У меня есть приложение Rails, размещенное на Heroku. Приложение создает и сохраняет файлы PDF на Amazon S3. Пользователи могут загружать эти файлы для просмотра в своем браузере или для сохранения на своем компьютере.

Проблема заключается в том, что, хотя загрузка этих файлов возможна через URL-адрес S3 (например, "https://s3.amazonaws.com/my-bucket/F4D8CESSDF.pdf" ), это, очевидно, НЕ является хорошим способ сделать это. Нежелательно предоставлять пользователю столько информации о бэкэнд, не говоря уже о проблемах безопасности, которые возникают.

Возможно ли, чтобы мое приложение каким-то образом извлекло данные файла из S3 в контроллере, а затем создало поток загрузки для пользователя, чтобы URL-адрес Amazon не был открыт?

4b9b3361

Ответ 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