Cómo descargar a través de HTTP única pieza de gran archivo con el rubí
Pregunta
Sólo tengo que descargar los primeros kilobytes de un archivo a través de HTTP.
He intentado
require 'open-uri'
url = 'http://example.com/big-file.dat'
file = open(url)
content = file.read(limit)
Pero en realidad descarga el archivo completo.
Solución
Esto parece funcionar cuando se utilizan enchufes:
require 'socket'
host = "download.thinkbroadband.com"
path = "/1GB.zip" # get 1gb sample file
request = "GET #{path} HTTP/1.0\r\n\r\n"
socket = TCPSocket.open(host,80)
socket.print(request)
# find beginning of response body
buffer = ""
while !buffer.match("\r\n\r\n") do
buffer += socket.read(1)
end
response = socket.read(100) #read first 100 bytes of body
puts response
Tengo curiosidad por si hay un "camino de rubí".
Otros consejos
Este es un hilo viejo, pero sigue siendo una pregunta sin respuesta que parece en su mayoría de acuerdo a mi investigación. He aquí una solución que se me ocurrió por Net mono-parches :: HTTP un poco:
require 'net/http'
# provide access to the actual socket
class Net::HTTPResponse
attr_reader :socket
end
uri = URI("http://www.example.com/path/to/file")
begin
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new(uri.request_uri)
# calling request with a block prevents body from being read
http.request(request) do |response|
# do whatever limited reading you want to do with the socket
x = response.socket.read(100);
end
end
rescue IOError
# ignore
end
El rescate atrapa el IOError que se inicia cuando se llama a HTTP.finish prematuramente.
Para su información, la toma de corriente dentro del objeto HTTPResponse
no es un verdadero objeto IO
(que es una clase llamada BufferedIO
interna), pero es bastante fácil de mono-parche que, también, para imitar los métodos IO
que necesita. Por ejemplo, otra biblioteca que estaba usando (exifr) necesita el método readchar
, que era fácil de añadir:
class Net::BufferedIO
def readchar
read(1)[0].ord
end
end
Confirmar " OpenURI devuelve dos objetos diferentes ". Es posible que pueda abusar de los métodos en que hay que interrumpir la descarga / tirar el resto del resultado después de un límite preestablecido.