Загрузить изображение с URL? - PullRequest
21 голосов
/ 21 июля 2011

Я пытаюсь использовать HTTP :: get для загрузки изображения диаграммы Google с созданного мной URL-адреса.

Это была моя первая попытка:

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(). Кто-нибудь знает, почему это так?

РЕШЕНИЕ:

После попытки выяснить, почему это происходит, я обнаружил " Как загрузить бинарный файл по 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 ]

54 голосов
/ 21 июля 2011

Я бы пошел за файлом, используя Ruby's 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-адрес, код обрабатывает его волшебным образом. Он также обрабатывает таймауты и повторяет попытки более изящно, если я правильно помню.

Если вам нужен более низкий контроль уровня, я бы посмотрел на один из многих других HTTP-клиентов для Ruby; 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.

Для целей документирования, вот что говорит URI при попытке проанализировать этот URL как есть:

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

Если я сначала закодирую URI, я получу успешный анализ. Дальнейшее тестирование с использованием Open :: URI показывает, что он может извлечь документ в этот момент и возвращает 23701 байт.

Я думаю, что это подходящее решение проблемы, если некоторые из этих символов действительно неприемлемы для URI И , они находятся вне RFC.

Просто для информации: Addressable :: URI является прекрасной заменой встроенному URI.

3 голосов
/ 21 июля 2011
    resp = http.get("/chart?#{failures_url")

Если вы скопировали исходный код, то в строке пути отсутствует пропущенная фигурная скобка.

0 голосов
/ 21 июля 2011

В исходной версии не было имени параметра для каждого параметра, только данные. Например, в заголовке нельзя просто отправить «Построения + за + последние + 12 + месяцы», но вместо этого должно быть «chtt = Сборки + за + последние + 12 + месяцы».

Попробуйте это:

failures_url  = ["title="+title, "type="+type, "data="+data, "size="+size, "colors="+colors, "labels="+labels].join("&")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...