从URL下载图像?

时间:2011-07-20 20:39:16

标签: ruby httpwebrequest javax.imageio

我正在尝试使用HTTP :: get从我创建的网址下载Google图表的图像。

这是我的第一次尝试:

failures_url  = [title, type, data, size, colors, labels].join("&")

require 'net/http'

Net::HTTP.start("http://chart.googleapis.com") { |http|
  resp = http.get("/chart?#{failures_url")
  open("pie.png" ,"wb") { |file|
    file.write(resp.body)
  }
}

只产生了一个空的PNG文件。

对于我的第二次尝试,我使用了failure_url调用中http.get()内存储的值。

require 'net/http'

Net::HTTP.start("http://chart.googleapis.com") { |http|
  resp = http.get("/chart?chtt=Builds+in+the+last+12+months&cht=bvg&chd=t:296,1058,1217,1615,1200,611,2055,1663,1746,1950,2044,2781,1553&chs=800x375&chco=4466AA&chxl=0:|Jul-2010|Aug-2010|Sep-2010|Oct-2010|Nov-2010|Dec-2010|Jan-2011|Feb-2011|Mar-2011|Apr-2011|May-2011|Jun-2011|Jul-2011|2:|Months|3:|Builds&chxt=x,y,x,y&chg=0,6.6666666666666666666666666666667,5,5,0,0&chxp=3,50|2,50&chbh=23,5,30&chxr=1,0,3000&chds=0,3000")
  open("pie.png" ,"wb") { |file|
    file.write(resp.body)
  }
}

并且,出于某种原因,即使第一次尝试在http.get()调用中具有相同的数据,此版本仍然有效。有谁知道这是为什么?

解决方案:

在试图弄清楚为什么会发生这种情况之后,我找到了“How do I download a binary file over HTTP?”。

其中一条评论提到在http://电话中删除Net::HTTP.start(...),否则将无法成功。在我这样做之后果然如此:

failures_url  = [title, type, data, size, colors, labels].join("&")

require 'net/http'

Net::HTTP.start("chart.googleapis.com") { |http|
  resp = http.get("/chart?#{failures_url")
  open("pie.png" ,"wb") { |file|
    file.write(resp.body)
  }
}

它有效。

3 个答案:

答案 0 :(得分:54)

我会使用Ruby的Open::URI

来查找文件
require "open-uri"

File.open('pie.png', 'wb') do |fo|
  fo.write open("http://chart.googleapis.com/chart?#{failures_url}").read 
end

我更喜欢Open :: URI的原因是它会自动处理重定向,所以当Google对其后端进行更改并尝试重定向URL时,代码会神奇地处理它。如果我没记错的话,它还可以更优雅地处理超时和重试。

如果你必须有较低级别的控制,那么我会看看Ruby的许多其他HTTP客户端之一; Net :: HTTP可以用于创建新服务或者当客户端不存在时,但我会使用Open :: URI或除了Net :: HTTP之外的东西,直到需要出现。


网址:

http://chart.googleapis.com/chart?chtt=Builds+in+the+last+12+months&cht=bvg&chd=t:296,1058,1217,1615,1200,611,2055,1663,1746,1950,2044,2781,1553&chs=800x375&chco=4466AA&chxl=0:|Jul-2010|Aug-2010|Sep-2010|Oct-2010|Nov-2010|Dec-2010|Jan-2011|Feb-2011|Mar-2011|Apr-2011|May-2011|Jun-2011|Jul-2011|2:|Months|3:|Builds&chxt=x,y,x,y&chg=0,6.6666666666666666666666666666667,5,5,0,0&chxp=3,50|2,50&chbh=23,5,30&chxr=1,0,3000&chds=0,3000

让URI失败。我怀疑是看到应该在URL中编码的字符。

出于文档目的,以下是在尝试按原样解析该URL时所说的内容:

URI::InvalidURIError: bad URI(is not URI?)

如果我首先编码URI,我会得到一个成功的解析。使用Open :: URI进一步测试表明它能够在该点检索文档并返回23701个字节。

我认为这是问题的适当解决方法,如果其中一些字符确实不被URI AND 接受,那么它们就不在RFC中了。

仅供参考,Addressable::URI gem是内置URI的绝佳替代品。

答案 1 :(得分:3)

    resp = http.get("/chart?#{failures_url")

如果您复制了原始代码,那么您在路径字符串中缺少一个结束的大括号。

答案 2 :(得分:0)

您的原始版本没有每个参数的参数名称,只有数据。例如,在标题上,你不能只提交“Builds + in + + last + 12 + months”,而是必须是“chtt = Builds + in + the + last + 12 + months”。

试试这个:

failures_url  = ["title="+title, "type="+type, "data="+data, "size="+size, "colors="+colors, "labels="+labels].join("&")