Почему при использовании OpenURI для загрузки файла получается неполный файл? - PullRequest
4 голосов
/ 06 декабря 2010

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

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

Вот код:

require 'open-uri'
open("#{Rails.root.to_s}/tmp/#{a.attachment_file_name}", "wb") do |file|  
  source_url = a.authenticated_url()
  io = open(URI.parse(source_url).to_s)
  file << io.read
  attachments[a.attachment_file_name] = File.read("#{Rails.root.to_s}/tmp/#{a.attachment_file_name}")        
end

a - это вложение от ActionMailer.

Есть идеи? Я был бы очень признателен за ваши мысли, так как я бился головой об стену на этом.

1 Ответ

9 голосов
/ 06 декабря 2010

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

Я бы сделал это так:

require 'open-uri'

source_url = a.authenticated_url()
attachment_file = "#{Rails.root.to_s}/tmp/#{a.attachment_file_name}"
open(attachment_file, "wb") do |file|  
  file.print open(source_url, &:read)
end

attachments[a.attachment_file_name] = File.read(attachment_file)

Похоже, source_url = a.authenticated_url() будет строкой, поэтому синтаксический анализ строки в URI с последующим выполнением to_s будет лишним, если URI не выполняет некоторую нормализацию, чего я не думаю.

Исходя из моего опыта сисадмина: побочной задачей является очистка загруженных / буферных файлов. Они могут быть удалены сразу после присоединения, или у вас может быть ежедневное задание cron, удаляющее все буферные файлы старше одного дня.

Дополнительной проблемой является отсутствие обработки ошибок, если URL не может быть прочитан, что приводит к сбою вложения. Используя временный буферный файл, вы можете проверить его наличие. Более того, вы, вероятно, должны быть готовы обработать исключение, если сервер возвращает ошибку 400 или 500.


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

require 'open-uri'

source_url = a.authenticated_url()
attachments[a.attachment_file_name] = open(source_url, &:read)
...