web-dev-qa-db-ja.com

URLから画像をダウンロードしますか?

HTTP :: getを使用して、作成したURLから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ファイルのみが生成されます。

2回目の試行では、http.get()呼び出し内の_failure_url_内に格納された値を使用しました。

_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()呼び出し内に同じデータがあったとしても、このバージョンは機能します。これがなぜか誰か知っていますか?

解決:

なぜこれが起こっているのかを理解しようとしたところ、「 HTTP経由でバイナリファイルをダウンロードするにはどうすればよいですか 」が見つかりました。

コメントの1つは、Net::HTTP.start(...)呼び出しで_http://_を削除することについて言及しています。そうしないと、成功しません。私がこれをやった後の案の定:

_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)
  }
}
_

出来た。

21
Hunter McMillen

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クライアントの1つを見てみます。 Net :: HTTPは、新しいサービスを作成する場合やクライアントが存在しない場合に適していますが、必要が現れるまで、Open :: URIまたはNet :: HTTP以外の何かを使用します。


URL:

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が言うことは次のとおりです。

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

最初にURIをエンコードすると、解析が成功します。 Open :: URIを使用してさらにテストすると、その時点でドキュメントを取得でき、23701バイトが返されることがわかります。

これらの文字の一部が本当にURIに受け入れられない場合[〜#〜]と[〜#〜]は、問題の適切な修正だと思いますそれらはRFCの範囲外です。

参考までに、 Addressable :: URI gemは組み込みURIの優れた代替品です。

55
the Tin Man
    resp = http.get("/chart?#{failures_url")

元のコードをコピーした場合は、パス文字列に閉じ中かっこがありません。

3
George

元のバージョンでは、各パラメーターのパラメーター名はなく、データのみでした。たとえば、タイトルでは「Builds + in + the + 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("&")
0
Jonathan M