140 votes

Comment est-ce que je télécharge un fichier binaire sur HTTP ?

Comment puis-je télécharger et enregistrer un fichier binaire sur HTTP à l’aide de Ruby ?

L’URL est `` .

Je suis sur la plate-forme Windows et je préférerais ne pas exécuter un programme externe.

149voto

Dawid Fatyga Points 2308

Le moyen le plus simple est la solution spécifique à la plateforme :

Probablement vous êtes à la recherche pour :

Edit : a changé. Merci.

Edit2 : La solution qui sauve la partie d’un fichier lors du téléchargement :

123voto

kikito Points 23229

Je sais que c’est une question ancienne, mais Google m’a jeté ici et je pense que j’ai trouvé une réponse plus simple.

Railscasts #179, Ryan Bates a utilisé la classe standard Ruby OpenURI faire beaucoup de ce qui était demandé comme ceci :

(Avertissement: non testé code. Vous devrez peut-être changer/tweak il.)

30voto

Arkku Points 15523

Exemple 3 de la Ruby documentation net/http indique comment pour télécharger un document sur HTTP et générer le fichier au lieu de juste il charger en mémoire, substitut met avec une écriture binaire dans un fichier, par exemple, comme indiqué dans la réponse de Dejw.

Des cas plus complexes apparaissent plus bas dans le même document.

28voto

krausefx Points 931

Vous pouvez utiliser open-uri, qui est une seule ligne

Ou en utilisant net/http

18voto

Isa Points 111

L'expansion sur Dejw réponse (edit2):

File.open(filename,'w'){ |f|
  uri = URI.parse(url)
  Net::HTTP.start(uri.host,uri.port){ |http| 
    http.request_get(uri.path){ |res| 
      res.read_body{ |seg|
        f << seg
#hack -- adjust to suit:
        sleep 0.005 
      }
    }
  }
}

filename et url sont des chaînes de caractères.

L' sleep de commande est un hack qui peut considérablement réduire l'utilisation du PROCESSEUR lorsque le réseau est le facteur limitant. Net::HTTP ne pas attendre pour le tampon (16 ko en v1.9.2) à remplir avant de céder, de sorte que le PROCESSEUR s'occupe lui-même de déménagement petits morceaux autour de. Dormir pendant un moment donne de la mémoire tampon une chance à combler entre l'écrit et l'utilisation du PROCESSEUR est comparable à un curl solution, 4-5x différence dans mon application. Une solution plus robuste pourrait examiner les progrès de l' f.pos et ajuster le délai d'attente de la cible, disons, 95% de la taille de la mémoire tampon -- en fait, c'est la façon dont j'ai reçu l'ordre de 0,005 nombre dans mon exemple.

Désolé, mais je ne sais pas un moyen plus élégant d'avoir des Rubis attendre le tampon à remplir.

Edit:

C'est une version qui s'adapte automatiquement à garder la mémoire tampon juste au niveau ou en dessous de leurs capacités. C'est une solution peu élégante, mais il semble être tout aussi rapide, et d'utiliser aussi peu de temps CPU, comme c'est l'appel à friser.

Il fonctionne en trois étapes. Une brève période d'apprentissage avec un dessein à long temps de sommeil établit la taille d'un tampon complète. La baisse de la période de réduit le temps de sommeil rapidement à chaque itération, en le multipliant par un grand facteur, jusqu'à ce qu'il trouve un sous-rempli de la mémoire tampon. Puis, au cours de la période normale, il ajuste en haut et en bas par un plus petit facteur.

Mon Ruby est un peu rouillé, donc je suis sûr que cela peut être amélioré. Tout d'abord, il n'y a pas d'erreur de manipulation. Aussi, peut-être il pourrait être séparé en un objet, loin de le téléchargement lui-même, de sorte que vous venais de l'appeler autosleep.sleep(f.pos) dans votre boucle? Encore mieux, Net::HTTP pourraient être modifiés à attendre un tampon complète avant de céder :-)

def http_to_file(filename,url,opt={})
  opt = {
    :init_pause => 0.1,    #start by waiting this long each time
                           # it's deliberately long so we can see 
                           # what a full buffer looks like
    :learn_period => 0.3,  #keep the initial pause for at least this many seconds
    :drop => 1.5,          #fast reducing factor to find roughly optimized pause time
    :adjust => 1.05        #during the normal period, adjust up or down by this factor
  }.merge(opt)
  pause = opt[:init_pause]
  learn = 1 + (opt[:learn_period]/pause).to_i
  drop_period = true
  delta = 0
  max_delta = 0
  last_pos = 0
  File.open(filename,'w'){ |f|
    uri = URI.parse(url)
    Net::HTTP.start(uri.host,uri.port){ |http|
      http.request_get(uri.path){ |res|
        res.read_body{ |seg|
          f << seg
          delta = f.pos - last_pos
          last_pos += delta
          if delta > max_delta then max_delta = delta end
          if learn <= 0 then
            learn -= 1
          elsif delta == max_delta then
            if drop_period then
              pause /= opt[:drop_factor]
            else
              pause /= opt[:adjust]
            end
          elsif delta < max_delta then
            drop_period = false
            pause *= opt[:adjust]
          end
          sleep(pause)
        }
      }
    }
  }
end

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