如何使用Net :: HTTP只读取正文的x个字节?

在阅读网页主体时,Ruby的Net :: HTTP方法似乎全有或全无。 我怎么能读到,只是身体的前100个字节?

我试图从内容服务器读取,如果请求的文件不可用,则在响应正文中返回一条简短的错误消息。 我需要阅读足够的正文以确定文件是否存在。 这些文件很庞大,所以我不想让整个机构检查文件是否可用。

这是一个旧线程,但根据我的研究,如何在Ruby中仅通过HTTP读取文件的一部分的问题仍然是一个大多数未解决的问题。 这是我通过猴子修补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); # be sure to call finish before exiting the block http.finish 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 

您是否应该只使用HTTP HEAD请求(Ruby Net::HTTP::Head方法)来查看资源是否存在,并且只有在获得2xx或3xx响应时才会继续? 这假设您的服务器配置为在文档不可用时返回4xx错误代码。 我认为这是正确的解决方案。

另一种方法是请求HTTP头并查看结果中的content-length标头值:如果您的服务器配置正确,您应该能够轻松地分辨短消息和长文档之间的长度差异。 另一种选择:在请求中设置content-range头字段(再次假定服务器正常运行WRT HTTP规范)。

我不认为你发送GET请求之后在客户端解决问题是要走的路:到那个时候,网络完成了繁重的工作,你不会真正节省任何浪费的资源。

参考: http标头定义

我想这样做一次,我唯一想到的就是猴子修补Net::HTTP#read_bodyNet::HTTP#read_body_0方法来接受一个长度参数,然后在前者中只传递长度参数到read_body_0方法,你只能读取长度字节。

要以块的forms读取HTTP请求的主体,您需要使用Net::HTTPResponse#read_body如下所示:

 http.request_get('/large_resource') do |response| response.read_body do |segment| print segment end end 

您确定内容服务器只返回一个简短的错误页面吗?

它是否也将HTTPResponse设置为适合404的东西。在这种情况下,您可以捕获在访问Net::HTTP.value()时引发的HTTPClientError派生exception(很可能是Net::HTTP.value()

如果您收到错误,那么如果您获得200,则文件不在那里,文件开始下载,您可以关闭连接。

你不能。 但你为什么需要? 当然,如果页面只是说该文件不可用,那么它将不是一个巨大的页面(即根据定义,文件不会在那里)?