2010-12-05 3 views
4

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

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

Вот код:

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.

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

ответ

9

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

Я хотел бы сделать это следующим образом:

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 не делают некоторую нормализацию, который я не думаю, что это так.

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

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


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

require 'open-uri' 

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

Спасибо! Вам известно, как читать приложение ActionMailer как StringIO? Так что мне не нужно использовать временный файл? – AnApprentice 2010-12-06 00:51:59