Ошибка получения файла CarrierWave S3 - неопределенный метод `body'

Это сводит меня с ума. Я использую CarrierWave с Amazon S3, я могу безопасно загрузить файл в корзину, и сейчас я пытаюсь (в другом запросе) извлечь файл и доставить его как загрузку в браузер.

Файлы могут быть чем угодно, ZIP-файл и т. Д. Я не использую его для хранения изображений.

Bucket является приватным, а не общедоступным, поэтому я не могу просто использовать S3 URL.

Вот мой код восстановления:

au = @note.attachment
au.retrieve_from_store!(File.basename(@note.attachment.to_s))
au.cache_stored_file!

Ошибки кода в файле cache_stored_file! линия. Выкидываю ошибку:

undefined method `body' for nil:NilClass

Я проверяю объект, и он выглядит нормально для меня, и если я вывожу @note.attachment, я ясно вижу URL-адрес amazon s3 с ключами и т. Д.

Я был во всем Интернете, и я могу понять это. Iv нашел несколько человек с такой же проблемой, которые решили ее, выполнив вещи, которые не имеют отношения к моему случаю (например, с помощью какого-либо метода imagemagick), опять же, это просто файлы.

Никакой обработки или работы с изображениями, я просто хочу вернуть файлы в браузер для загрузки.

Может кто-нибудь, пожалуйста, помогите?

Вот мой загрузчик:

class AttachmentUploader < CarrierWave::Uploader::Base

  storage :fog

  def store_dir
    "#{Rails.env}/#{model.id}"
  end

  def cache_dir
    "#{Rails.root}/tmp/attachments"
  end
end

и след

carrierwave (0.8.0) lib/carrierwave/storage/fog.rb:225:in `read'
carrierwave (0.8.0) lib/carrierwave/uploader/cache.rb:77:in `sanitized_file'
carrierwave (0.8.0) lib/carrierwave/uploader/cache.rb:116:in `cache!'
carrierwave (0.8.0) lib/carrierwave/uploader/cache.rb:73:in `cache_stored_file!'

1 ответ

Решение

Я думаю, что эти строки не имеют смысла:

au = @note.attachment
au.retrieve_from_store!(File.basename(@note.attachment.to_s))
au.cache_stored_file!

retrieve_from_store это то, что вы обычно вызываете в загрузчике, а не в прикрепленном объекте. Сложный шаг передачи базового имени вложения сам по себе должен привести к тому, что предупреждающие звонки сработают повсюду.

Если я вас правильно понимаю, вы просто хотите дать пользователю возможность загрузить файл, который вы сохранили в S3.

Вы можете сделать это несколькими способами.

Проще всего позвонить @note.attachment.url и распечатайте URL как ссылку, по которой пользователь может щелкнуть.

Другой способ - перенаправить пользователя на URL в действии контроллера.

# notes/1/download_attachment   
def download_attachment
  @note = Note.find(params[:id)
  redirect_to @note.attachment.url
end

Последний способ - выступить в роли прокси-сервера / кэша, извлечь файл из S3 и вернуть его.

Вы можете сделать это примерно так в вашем контроллере:

file = open(@note.attachment.url)
send_data file

Обратите внимание, что у меня не было возможности протестировать этот последний фрагмент кода.

Вы можете прочитать больше о send_data здесь.

Другие вопросы по тегам