如何在使用Ruby的OpenUri下载之前获取HTTP头

我目前正在使用OpenURI在Ruby中下载文件。 不幸的是,似乎无法在不下载完整文件的情况下获取HTTP标头:

open(base_url, :content_length_proc => lambda {|t| if t && 0  t) end }, :progress_proc => lambda {|s| pbar.progress = s if pbar }) {|io| puts io.size puts io.meta['content-disposition'] } 

运行上面的代码表明它首先下载完整的文件,然后才打印我需要的标题。

有没有办法在下载完整文件之前获取标题,所以如果标题不是我期望的那样,我可以取消下载?

您可以使用Net :: HTTP来解决此问题,例如:

 require 'net/http' http = Net::HTTP.start('stackoverflow.com') resp = http.head('/') resp.each { |k, v| puts "#{k}: #{v}" } http.finish 

另一个例子,这次获得精彩书籍的标题, 使用ANSI-C进行面向对象编程

 require 'net/http' http = Net::HTTP.start('www.planetpdf.com') resp = http.head('/codecuts/pdfs/ooc.pdf') resp.each { |k, v| puts "#{k}: #{v}" } http.finish 

看起来我想要的是不可能使用OpenURI,至少不是,正如我所说的,不首先加载整个文件。

我能够使用Net :: HTTP的request_get做我想做的事情

这是一个例子:

 http.request_get('/largefile.jpg') {|response| if (response['content-length'] < max_length) response.read_body do |str| # read body now # save to file end end } 

请注意,这仅在使用块时有效,如下所示:

 response = http.request_get('/largefile.jpg') 

身体已经被阅读了。

而不是使用Net :: HTTP,这可能就像使用沙铲在海滩上挖掘池一样,您可以使用许多HTTP客户端来处理Ruby并清理代码。

以下是使用HTTParty的示例:

 require 'httparty' resp = HTTParty.head('http://example.org') resp.headers # => {"accept-ranges"=>["bytes"], "cache-control"=>["max-age=604800"], "content-type"=>["text/html"], "date"=>["Thu, 02 Mar 2017 18:52:42 GMT"], "etag"=>["\"359670651\""], "expires"=>["Thu, 09 Mar 2017 18:52:42 GMT"], "last-modified"=>["Fri, 09 Aug 2013 23:54:35 GMT"], "server"=>["ECS (oxr/83AB)"], "x-cache"=>["HIT"], "content-length"=>["1270"], "connection"=>["close"]} 

此时,很容易检查文档的大小:

 resp.headers['content-length'] # => "1270" 

不幸的是,你正在谈论的HTTPd可能不知道内容会有多大; 为了快速响应服务器,不一定要计算动态生成的输出的大小,这将花费几乎与实际发送它一样长的CPU密集度,因此依赖于“内容长度”值可能是错误的。

Net :: HTTP的问题是它不会自动处理重定向,因此您必须添加其他代码。 当然,该代码在文档中提供,但代码随着您需要做更多事情而不断增长,直到您最终编写了另一个http客户端(YAHC)。 所以,避免这种情况并使用现有的车轮。