看起来Ruby的Net::HTTP方法在读取网页正文时都是一刀切的。有没有办法只读取前100个字节?
我正在尝试从一个内容服务器中读取数据。如果请求的文件不存在,服务器会在响应正文中返回一个短错误消息。我需要读取足够的正文来确定文件是否存在,但这些文件非常大,所以我不想获取整个正文仅仅为了检查文件是否存在。
这是一个旧帖子,但是我的研究表明,在Ruby中如何通过HTTP仅读取文件的一部分仍然是一个大多数未被解答的问题。这是我通过对Net::HTTP进行一些猴子补丁(monkey-patch)所想出的解决方案:
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时,救援(rescue)会捕获抛出的IOError。
顺便说一下,在HTTPResponse
对象中的套接字并不是真正的IO
对象(它是一个名为BufferedIO
的内部类),但很容易通过改写代码来模拟所需的IO
方法。例如,我正在使用的另一个库(exifr)需要添加readchar
方法:
class Net::BufferedIO
def readchar
read(1)[0].ord
end
end
HEAD
请求(Ruby的 Net::HTTP::Head
方法)来查看资源是否存在,并仅在收到2xx或3xx响应时继续进行? 这假定您的服务器已配置为返回4xx错误代码,如果文档不可用。我认为这是正确的解决方案。content-length
标头值:如果您的服务器已正确配置,则应能够轻松区分短消息和长文档之间的长度差异。 另一种选择是在请求中设置content-range
标头字段(再次假设服务器根据HTTP规范正确运行)。HEAD
是从客户端出发的正确方式。如果他们的服务器出现问题,他们需要修复它。不幸的是,这并不会让 OP 的任务变得更容易,因为公司和供应商通常不关心使用内容时遇到的问题,当黑客攻击他们的服务器时也是如此。 - the Tin Man我曾经想过这样做,唯一能想到的方法就是对Net::HTTP#read_body
和Net::HTTP#read_body_0
方法进行猴子补丁以接受长度参数,然后在前者中将长度参数传递给read_body_0
方法,在该方法中只读取指定长度的字节数。
Net :: HTTPResponse#read_body
:http.request_get('/large_resource') do |response|
response.read_body do |segment|
print segment
end
end
您确定内容服务器只返回了一张简短的错误页面吗?
它是否还将HTTPResponse
设置为适当的值,例如404?如果是这样,您可以捕获HTTPClientError
派生的异常(最可能是HTTPNotFound
),当访问Net::HTTP.value()
时会出现该异常。
如果您收到错误,则说明该文件不存在;如果您收到200,则表示该文件已经开始下载,此时可以关闭连接。
你不能这样做。但是你为什么需要这样做呢?如果页面只是显示文件不可用,那么它不会是一个很大的页面(也就是说,按照定义,该文件不存在)。
request = Net::HTTP::Get.new(uri.request_uri, {'Accept-Encoding' => 'entity'})
来禁用压缩。请注意,如果响应是分块的,则首先会得到一个带有块大小的行,以十六进制表示。因此,response.socket.read(100)
将产生一行带有十六进制数字64
,以及另一行带有100个八位组(或多行带有较小的大小,如果服务器发送较小的块)。 - Arjan