Альтернатива X-sendfile в Apache для отправки файла с заданным URL? - PullRequest
3 голосов
/ 09 декабря 2010

Я пишу приложение Rails, которое обслуживает файлы, хранящиеся на удаленном сервере, конечному пользователю.

В моем случае файлы хранятся на S3, но пользователь запрашивает файл через Rails-приложение (скрывая фактический URL). Если файл находился на локальной файловой системе моего сервера, я мог бы использовать заголовок Apache X-Sendfile, чтобы освободить процесс Ruby для других запросов, пока Apache взял на себя задачу отправки файла клиенту. Но в моем случае - когда файл находится не в локальной файловой системе, а на S3 - кажется, что я вынужден временно загрузить его в Rails, прежде чем отправить его клиенту.

Нет ли у Apache способа передать «удаленный» файл клиенту, который на самом деле не находится на самом сервере. Я не возражаю, если Apache должен загрузить файл, чтобы это работало, если мне не нужно связывать процесс Ruby, пока он продолжается.

Есть предложения?

1 Ответ

1 голос
/ 28 декабря 2010

Томас, у меня похожие требования / проблемы, и я думаю, что смогу ответить на твою проблему. Во-первых (и я не уверен на 100%, что вы заботитесь об этой части), скрыть URL-адрес S3 довольно просто, поскольку Amazon позволяет вам указывать CNAMES на ваш контейнер и использовать собственный URL-адрес вместо URL-адреса amazon. Для этого вам нужно указать свой DNS на правильный URL-адрес Amazon. Когда я настроил мой, это было похоже на это: files.domain.com указывает на files.domain.com.s3.amazonaws.com. Затем вам нужно создать корзину с именем вашего пользовательского URL (files.domain.com в этом примере). Как называется этот URL, будет отличаться в зависимости от того, какой гем вы используете, но предупреждающим словом было то, что плагин attachment_fu, который я использовал, неправильно отправлял меня на files.domain.com/files.domain.com/name_of_file .... Я не смог найти настройки, чтобы исправить это, поэтому простой метод .sub для S3-части плагина исправил это.

Что касается других ваших вопросов, чтобы выполнить некоторый код рельсов (например, записать попадание в БД) перед загрузкой, вы можете просто сделать это:

def download
  file = File.find(...
  # code to record 'hit' to database
  redirect_to 3Object.url_for(file.filename, 
                              bucket,
                              :expires_in => 3.hours)
end

Этот код все равно заставит файл обслуживаться S3, но все же даст вам возможность запустить некоторый ruby. (Конечно, приведенный выше код не будет работать как есть, вам нужно будет указать ему правильный файл и корзину, а мои ключи amazon сохраняются в файле конфигурации. Выше также используется синтаксис для гема AWS :: S3 - http://amazon.rubyforge.org/).

Во-вторых, проблема Content-Disposition: вложение немного сложнее. Надеемся, что ваша ситуация немного проще, чем моя, и может помочь следующее решение. Предполагая, что объект 'file' (в этом примере) является правильным объектом S3, вы можете установить расположение для прикрепления с помощью

file.content_disposition = "attachment"
file.save

Приведенный выше код может быть выполнен после того, как файл существует на сервере S3 (в отличие от некоторых других заголовков и разрешений), что приятно, и его также можно добавлять при загрузке файла (синтаксис зависит от вашего плагина). Я все еще пытаюсь найти способ сообщить S3, что нужно отправлять его как вложение и только по запросу (не каждый раз), и, если вы обнаружите это, сообщите мне ваше решение. Мне нужно иметь возможность иногда загружать его, а иногда сохранять встраиваемые изображения (например) в HTML. Я не использую вышеупомянутый редирект, но, к счастью, кажется, что если вы вставляете (например, тег HTML-изображения) файл с заголовком content-disposition / attachment, и браузер по-прежнему отображает изображение нормально (но я не тщательно протестировал это в достаточном количестве браузеров, чтобы отправить его в дикую природу).

Надеюсь, это поможет! Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...