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.
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.
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.)
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.
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
}
}
}
}
où 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 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.