Как мне прочитать только x количество байтов тела, используя Net :: HTTP? - PullRequest
12 голосов
/ 17 сентября 2008

Кажется, что методы Ruby's Net :: HTTP - все или ничего, когда дело доходит до чтения тела веб-страницы. Как я могу прочитать, скажем, только первые 100 байтов тела?

Я пытаюсь прочитать с сервера содержимого, который возвращает короткое сообщение об ошибке в теле ответа, если запрошенный файл недоступен. Мне нужно прочитать достаточно тела, чтобы определить, есть ли файл там. Файлы огромные, поэтому я не хочу, чтобы все тело проверялось, доступен ли файл.

Ответы [ 6 ]

13 голосов
/ 22 декабря 2011

Это старая ветка, но, как показывают мои исследования, вопрос о том, как читать только часть файла через HTTP в Ruby, до сих пор остается в основном без ответа. Вот решение, которое я придумал, немного исправив Net :: HTTP:

require 'net/http'

# provide access to the actual socket
class Net::HTTPResponse
  attr_reader :socket
end

uri = URI("http://www.example.com/path/to/file")
begin
  Net::HTTP.start(uri.host, uri.port) do |http|
    request = Net::HTTP::Get.new(uri.request_uri)
    # calling request with a block prevents body from being read
    http.request(request) do |response|
      # do whatever limited reading you want to do with the socket
      x = response.socket.read(100);
      # be sure to call finish before exiting the block
      http.finish
    end
  end
rescue IOError
  # ignore
end

Спасатель ловит IOError, который выдается при преждевременном вызове HTTP.finish.

К вашему сведению, сокет в объекте HTTPResponse не является истинным объектом IO (это внутренний класс с именем BufferedIO), но довольно просто сделать обезьяну-патч, которая тоже имитирует IO методы, которые вам нужны. Например, другая библиотека, которую я использовал (exifr), нуждалась в методе readchar, который было легко добавить:

class Net::BufferedIO
  def readchar
    read(1)[0].ord
  end
end
12 голосов
/ 17 сентября 2008

Разве вы не должны просто использовать HTTP HEAD запрос (метод Ruby Net::HTTP::Head), чтобы увидеть, есть ли ресурс, и продолжить, только если вы получите ответ 2xx или 3xx? Это предполагает, что ваш сервер настроен на возврат кода ошибки 4xx, если документ недоступен. Я бы сказал, что это было правильное решение.

Альтернатива - запросить заголовок HTTP и посмотреть в результате значение заголовка content-length: если ваш сервер правильно настроен, вы легко сможете определить разницу в длине короткого сообщения и длинного документа. , Другой вариант: установите в запросе поле заголовка content-range (что опять-таки предполагает, что сервер ведет себя корректно в спецификации HTTP).

Я не думаю, что решение проблемы в клиенте после , когда вы отправили запрос GET, - это путь: к тому времени сеть уже сделала тяжелую работу, и вы выиграли действительно не тратьте впустую потраченные ресурсы.

Ссылка: определения заголовка http

3 голосов
/ 17 сентября 2008

Я хотел сделать это один раз, и единственное, о чем я мог подумать - это обезьяна, исправляющая методы Net::HTTP#read_body и Net::HTTP#read_body_0, чтобы принять параметр длины, а затем в первом просто передать параметр длины в read_body_0 метод, где вы можете читать только длину байтов.

2 голосов
/ 17 сентября 2008

Чтобы прочитать тело HTTP-запроса в чанках, вам нужно использовать Net::HTTPResponse#read_body, например:

http.request_get('/large_resource') do |response|
  response.read_body do |segment|
    print segment
  end
end
2 голосов
/ 17 сентября 2008

Вы уверены, что контент-сервер возвращает только короткую страницу ошибки?

Разве это не устанавливает HTTPResponse на что-то подходящее, например 404. В этом случае вы можете перехватить производное исключение HTTPClientError (наиболее вероятно HTTPNotFound), которое возникает при доступе к Net::HTTP.value().

Если вы получили ошибку, то ваш файл не был там, если вы получили 200, файл начинает загружаться, и вы можете закрыть соединение.

0 голосов
/ 17 сентября 2008

Вы не можете. Но зачем тебе это? Конечно, если страница просто говорит, что файл недоступен, то это не будет огромная страница (т.е. по определению файл не будет там)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...