2008-09-17 30 views
12

在閱讀網頁正文時,似乎Ruby的Net :: HTTP的方法全是或全無。我怎樣才能讀取身體的前100個字節?如何使用Net :: HTTP只讀取身體的x個字節?

我試圖從在響應的身體返回短錯誤消息,如果請求的文件不可用內容服務器來讀取。我需要閱讀足夠的內容才能確定文件是否存在。這些文件是巨大的,所以我不想讓整個機構檢查文件是否可用。

回答

-3

你不能。但爲什麼你需要?當然,如果頁面只是說文件不可用,那麼它不會是一個巨大的頁面(即根據定義,文件不會在那裏)?

+0

這不是一個答案。這是你無法想象的東西可能是必要/有用/可取的,因爲你個人還沒有遇到過。誰在乎他爲什麼需要?誰在乎,如果你有這個問題的最終結果?問題是「如何使用Net :: HTTP只讀取身體的x個字節?」 「。你知不知道怎麼?如果不是,你爲什麼要浪費每個人的帶寬? – 2017-03-10 07:48:03

2

確定的內容服務器只返回一個簡短的錯誤頁面?

不還設置HTTPResponse適當的像404的東西在這種情況下你可以捕獲HTTPClientError派生的異常(最有可能HTTPNotFound)的訪問時Net::HTTP.value()提高。

如果你得到一個錯誤,那麼如果你得到200文件開始下載,你可以關閉連接您的文件是不存在。

2

要讀取的塊HTTP請求的身體,你需要使用Net::HTTPResponse#read_body這樣的:

http.request_get('/large_resource') do |response| 
    response.read_body do |segment| 
    print segment 
    end 
end 
+2

試過這個。 request_get仍然希望在處理該塊之前下載整個文件。 – bvanderw 2008-09-17 13:36:14

+0

這對我的分塊響應(使用`Transfer-Encoding:chunked`)有效,如果我在兩個塊(在兩個「end」之前)都添加一個「break」以在獲得第一個塊之後停止。在這種情況下,使用帶有`read_body`的塊使Ruby不會讀取完整的響應(甚至不會等待它)。但是,再次說明:我的回答大致是從一開始,而這些都是小塊。我懷疑HTTP允許客戶端明確請求分塊響應,也不允許它建議最大塊大小;如果服務器不返回(小)塊,似乎應該使用`Range`頭。 – Arjan 2015-05-01 12:49:09

12

你不應該只使用一個HTTP請求HEAD(紅寶石Net::HTTP::Head方法),看是否資源是否存在,並且只有在獲得2xx或3xx響應時纔會繼續?這假定您的服務器配置爲在文檔不可用時返回4xx錯誤代碼。我會認爲這是正確的解決方案。

另一種方法是請求HTTP頭並查看結果中的content-length標頭值:如果您的服務器配置正確,您應該能夠輕鬆地分辨出短消息和長文檔之間的長度差異。另一種方法是:在請求中設置content-range標頭字段(它再次假定服務器的行爲正確WRT HTTP規範)。

我不認爲解決客戶端之後之後發送GET請求的問題是一條可行之路:到那時,網絡已經完成了繁重的工作,而且您不會真的節省浪費的資源。

參考:http header definitions

+1

試過,服務器發送一個OK響應和一個0的內容長度。這是Perforce的P4Web服務器。 – bvanderw 2008-09-17 13:34:43

+3

嗯。如果你的供應商發送200 OK,當它真的意味着404沒有找到時,你應該提高優先級bugrep! – 2008-09-17 14:49:35

3

我想做這一次,我能想到的唯一的事情就是猴子修補Net::HTTP#read_bodyNet::HTTP#read_body_0方法接受一個長度參數,然後在前者只是通過長度參數寫入read_body_0方法,其中只能讀取長度字節。

12

這是一個古老的線程,但如何通過Ruby的HTTP只讀文件的一部分的問題仍然是根據我的研究大多是沒有答案的。這是我想出了一個解決方案由猴子修補的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 

救援捕捉,當你調用過早那HTTP.finish拋出真實的IO錯誤。

僅供參考,HTTPResponse對象中的插座是不是一個真正的IO對象(這就是所謂的​​一個內部類),但它很容易猴補丁,也模仿你所需要的IO方法。例如,我正在使用的另一個庫(exifr)需要readchar方法,該方法很容易添加:

class Net::BufferedIO 
    def readchar 
    read(1)[0].ord 
    end 
end