我只需要通过 HTTP 下载文件的前几千字节。
我试过
require 'open-uri'
url = 'http://example.com/big-file.dat'
file = open(url)
content = file.read(limit)
但它实际上下载了完整的文件。
这似乎在使用套接字时起作用:
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
我很好奇是否有“红宝石方式”。
这是一个旧线程,但根据我的研究,这仍然是一个似乎大部分没有答案的问题。这是我通过猴子修补 Net::HTTP 提出的一个解决方案:
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
救援捕获了当您过早调用 HTTP.finish 时引发的 IOError。
仅供参考,对象中的套接字HTTPResponse
不是真正的IO
对象(它是一个名为 的内部类BufferedIO
),但也很容易对其进行修补,以模仿IO
您需要的方法。例如,我正在使用的另一个库 (exifr) 需要该readchar
方法,该方法很容易添加:
class Net::BufferedIO
def readchar
read(1)[0].ord
end
end
查看“ OpenURI 返回两个不同的对象”。您可能会滥用其中的方法来中断下载/在预设限制后丢弃剩余的结果。