2009-08-31 10 views
3

J'ai une méthode webservice qui lit une photo et retourne ses données d'octets. Je suis actuellement en train de faire ce qui suit:Est-ce que ruby ​​IO.read() verrouille?

@photo_bytes = IO.read("/path/to/file") 
send_data(@photo_bytes, :filename => "filename", :type => "filetype", :disposition => "inline") 

Je reçois un comportement étrange en appelant beaucoup ... occasionnellement send_data retourne null. Je pense que peut-être je reçois des conflits de lecture si un fichier n'a pas encore été fermé. Ai-je besoin de fermer explicitement le fichier après l'avoir ouvert avec IO.read? Comment pourrais-je utiliser read_nonblock pour le faire et cela en vaudrait-il la peine?

MISE À JOUR:

J'ai donc fait un peu plus de temps à l'exploitation forestière et IO.read renvoie une valeur comme 1800 octets quand il retourne habituellement ~ 5800 octets pour une image. Quand il renvoie 1800 octets, l'image n'apparaît pas sur le client. Cela se produit de manière assez aléatoire lorsque deux utilisateurs appellent le service Web.

Merci

Tom

Répondre

4

La méthode IO.read ne fait pas Verrouille le fichier, et ainsi ne devrait pas être affectée par d'autres lecteurs simultanés. Toutefois, si vous avez du code ailleurs dans votre application et que écrit sur le même chemin, vous devez vous assurer de mettre à jour le fichier de manière atomique. L'ouverture d'un fichier en mode write (pas append) tronque immédiatement le fichier à zéro octet, donc jusqu'à ce que la nouvelle version ait été écrite, vous pourriez bien voir des réponses vides générées à partir de l'extrait ci-dessus.

En supposant que vous êtes sur une plate-forme * NIX comme Linux ou OS X, cependant, vous pouvez mettre à jour un fichier atomiquement en utilisant le code comme ceci:

require 'tempfile' 
require 'fileutils' 

def safe_write(path, data) 
    tmp = Tempfile.new 
    tmp.write(data) 
    tmp.close 
    FileUtils.mv(tmp.path, path) 
end 

Cela écrire des données dans un fichier temporaire, puis déplacez à l'emplacement "/path/to/file" atomiquement, sans lecteurs jamais voir la version tronquée de longueur nulle.

+0

Une fois qu'un fichier donné est écrit, il ne sera jamais mis à jour. Ceci est un système de photo de profil. L'utilisateur télécharge la photo, elle est récupérée plusieurs fois par différents utilisateurs. Si l'utilisateur télécharge une nouvelle photo, un nouveau fichier est créé. Il semble que send_data envoie un fichier null de temps en temps lorsque de nombreux utilisateurs accèdent au site. – cakeforcerberus

+0

Et par "beaucoup", je veux dire deux. :) – cakeforcerberus

+0

Oh, aussi, je tire aussi les données avec <% image_tag filename%> - NE verrouille-t-il pas le fichier? – cakeforcerberus

Questions connexes