231 votes

Comment puis-je télécharger un fichier à partir d'une URL et l'enregistrer dans Rails ?

Je dispose d'une URL vers une image que je souhaite enregistrer localement, afin de pouvoir utiliser Paperclip pour produire une vignette pour mon application. Quelle est la meilleure façon de télécharger et de sauvegarder l'image ? (J'ai regardé dans ruby file handling mais je n'ai rien trouvé).

337voto

Levi Points 2212

Essayez ça :

require 'open-uri'
open('image.png', 'wb') do |file|
  file << open('http://example.com/image.png').read
end

1 votes

Ça marche. Merci. J'ai essayé cela sur une image. L'image n'a pas été correctement écrite dans le fichier. Comme si elle avait été corrompue ou autre. Pouvez-vous également me guider pour faire la même chose dans une application Rails. Puis-je utiliser ceci dans une application Rails ?

0 votes

Oui, vous pouvez l'utiliser dans une application rails. Le fichier qui ne s'écrit pas correctement est probablement dû au fait que j'ai oublié d'ouvrir la destination en mode write-binary. Je vais le modifier maintenant.

97 votes

Cette opération permet de lire l'ensemble du fichier en mémoire. Le meilleur moyen est IO.copy_stream(open('http://example.com/image.png'), 'destination.png')

187voto

Clemens Helm Points 351

Une version encore plus courte :

require 'open-uri'
download = open('http://example.com/image.png')
IO.copy_stream(download, '~/image.png')

Pour conserver le même nom de fichier :

IO.copy_stream(download, "~/#{download.base_uri.to_s.split('/')[-1]}")

4 votes

Et plus efficace car le résultat n'est pas stocké sous forme de chaîne de caractères en mémoire. +1

3 votes

Il est cependant utile que les deux réponses soient affichées, afin que les personnes comme moi puissent voir les deux, réfléchir aux différences et choisir cette réponse en toute connaissance de cause, pour les bonnes raisons :)

9 votes

Je reçois un avertissement de sécurité de la part de Rubocop lorsque j'utilise open . Je l'ai remplacé par URI.parse(url).open à la place. Pour en savoir plus sur ce policier, cliquez ici : rubydoc.info/gems/rubocop/RuboCop/Cop/Security/Open

32voto

superluminary Points 5496

Si vous utilisez PaperClip, le téléchargement à partir d'une URL est désormais géré automatiquement.

En supposant que vous avez quelque chose comme :

class MyModel < ActiveRecord::Base
  has_attached_file :image, ...
end

Sur votre modèle, il suffit de spécifier l'image sous forme d'URL, quelque chose comme ceci (écrit délibérément à la main) :

@my_model = MyModel.new
image_url = params[:image_url]
@my_model.image = URI.parse(image_url)

Vous voudrez probablement mettre cela dans une méthode de votre modèle. Cela fonctionnera également très bien sur le système de fichiers temporaires de Heroku.

Paperclip s'en chargera à partir de là.

source : documentation sur le trombone

5 votes

Pour les futurs chercheurs, le Paperclip ne permet plus cela par défaut : medium.com/in-the-weeds/

19voto

Sage Ross Points 293

Je pense que c'est la manière la plus claire :

require 'open-uri'

File.write 'image.png', open('http://example.com/image.png').read

0 votes

Je suis novice en matière de rails, où puis-je ajouter ce code dans le modèle, le contrôleur ou la vue ?

1 votes

Cela dépend, mais en général vous feriez quelque chose comme ça dans un modèle ou une méthode de contrôleur. Dans un contexte Rails, il est préférable d'utiliser les outils du framework comme ActiveStorage, plutôt que d'écrire directement sur le disque.

13voto

user5783745 Points 1214

C'est sans doute le moyen le plus simple :

require 'open-uri'
image_url = "https://i.imgur.com/ZWnhY9T.png"
IO.copy_stream(URI.open(image_url), 'destination.png')

1 votes

Dans mon cas, j'ai essayé tous les codes ci-dessus, mais seul cet étage a fonctionné. La différence est le premier paramètre de copy_stream() URI.open(img_url) Si je n'enveloppe pas le img_url par URI.open() J'ai obtenu l'ERREUR suivante No such file or directory @ rb_sysopen .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X