2010-12-05 1 views
4

J'essaie d'utiliser OpenURI pour télécharger un fichier à partir de S3, puis l'enregistrer localement afin que je puisse envoyer le fichier en pièce jointe avec ActionMailer.Pourquoi l'utilisation d'OpenURI pour télécharger un fichier entraîne-t-elle un fichier partiel?

Quelque chose d'étrange se passe. Les images téléchargées et attachées sont corrompues, les parties inférieures des images sont manquantes.

Voici le code:

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 est la pièce jointe ActionMailer.

Des idées? J'apprécierais vraiment vos pensées, car je me suis cogné la tête contre le mur sur celui-ci.

Répondre

9

Il semble que vous essayez de lire le fichier avant qu'il ne soit fermé, ce qui pourrait laisser une partie du tampon de fichier non écrite.

Je ferais comme ça:

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) 

Il ressemble source_url = a.authenticated_url() sera une chaîne, l'analyse syntaxique de sorte que la chaîne en URI faisant alors to_s dessus sera redondant, sauf si URI fait une normalisation, ce que je ne pense pas. En fonction de mon expérience avec sysadmin: Une tâche secondaire consiste à nettoyer les fichiers téléchargés/spoulés. Ils pourraient être supprimés immédiatement après avoir été attachés, ou vous pourriez avoir un travail cron qui s'exécute tous les jours, la suppression de tous les fichiers spoulés sur un jour.

Une autre préoccupation à ce sujet est qu'il n'y a pas de gestion des erreurs dans le cas où l'URL ne peut pas être lu, provoquant l'échec de la pièce jointe. À l'aide d'un fichier spool temporaire, vous pouvez vérifier l'existence du fichier. Mieux encore, vous devriez probablement être prêt à gérer une exception si le serveur renvoie une erreur 400 ou 500.


Pour éviter d'utiliser un fichier de bobine temporaire essayer ce code non testé:

require 'open-uri' 

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

Merci! Savez-vous comment lire une pièce jointe ActionMailer en tant que StringIO? Donc je n'ai pas besoin d'utiliser un fichier temporaire? – AnApprentice

Questions connexes