9

我目前正在使用 OpenURI 在 Ruby 中下载文件。不幸的是,如果不下载完整文件,似乎不可能获得 HTTP 标头:

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

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

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

4

3 回答 3

11

你可以使用 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
于 2013-07-03T18:47:27.263 回答
5

似乎我想要的东西是不可能使用 OpenURI 来归档的,至少不是,正如我所说,如果不先加载整个文件。

我能够使用 Net::HTTP's 做我想做的事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')

正文将已被读取。

于 2013-07-15T23:04:36.703 回答
3

与其使用 Net::HTTP,这就像使用沙铲在海滩上挖一个水池一样,您可以使用一些用于 Ruby 的 HTTP 客户端并清理代码。

这是一个使用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)。所以,避免这种情况并使用现有的轮子。

于 2017-03-02T18:57:36.180 回答