2008-09-17 33 views
12

在阅读网页正文时,似乎Ruby的Net :: HTTP的方法全是或全无。我怎样才能读取身体的前100个字节?如何使用Net :: HTTP只读取身体的x个字节?

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

回答

-3

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

+0

这不是一个答案。这是你无法想象的东西可能是必要/有用/可取的,因为你个人还没有遇到过。谁在乎他为什么需要?谁在乎,如果你有这个问题的最终结果?问题是“如何使用Net :: HTTP只读取身体的x个字节?” “。你知不知道怎么?如果不是,你为什么要浪费每个人的带宽? – 2017-03-10 07:48:03

2

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

不还设置HTTPResponse适当的像404的东西在这种情况下你可以捕获HTTPClientError派生的异常(最有可能HTTPNotFound)的访问时Net::HTTP.value()提高。

如果你得到一个错误,那么如果你得到200文件开始下载,你可以关闭连接您的文件是不存在。

2

要读取的块HTTP请求的身体,你需要使用Net::HTTPResponse#read_body这样的:

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

试过这个。 request_get仍然希望在处理该块之前下载整个文件。 – bvanderw 2008-09-17 13:36:14

+0

这对我的分块响应(使用`Transfer-Encoding:chunked`)有效,如果我在两个块(在两个“end”之前)都添加一个“break”以在获得第一个块之后停止。在这种情况下,使用带有`read_body`的块使Ruby不会读取完整的响应(甚至不会等待它)。但是,再次说明:我的回答大致是从一开始,而这些都是小块。我怀疑HTTP允许客户端明确请求分块响应,也不允许它建议最大块大小;如果服务器不返回(小)块,似乎应该使用`Range`头。 – Arjan 2015-05-01 12:49:09

12

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

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

我不认为解决客户端之后之后发送GET请求的问题是一条可行之路:到那时,网络已经完成了繁重的工作,而且您不会真的节省浪费的资源。

参考:http header definitions

+1

试过,服务器发送一个OK响应和一个0的内容长度。这是Perforce的P4Web服务器。 – bvanderw 2008-09-17 13:34:43

+3

嗯。如果你的供应商发送200 OK,当它真的意味着404没有找到时,你应该提高优先级bugrep! – 2008-09-17 14:49:35

3

我想做这一次,我能想到的唯一的事情就是猴子修补Net::HTTP#read_bodyNet::HTTP#read_body_0方法接受一个长度参数,然后在前者只是通过长度参数写入read_body_0方法,其中只能读取长度字节。

12

这是一个古老的线程,但如何通过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抛出真实的IO错误。

仅供参考,HTTPResponse对象中的插座是不是一个真正的IO对象(这就是所谓的​​一个内部类),但它很容易猴补丁,也模仿你所需要的IO方法。例如,我正在使用的另一个库(exifr)需要readchar方法,该方法很容易添加:

class Net::BufferedIO 
    def readchar 
    read(1)[0].ord 
    end 
end