2013-07-03 71 views
9

我目前使用OpenURI來下載Ruby文件。不幸的是,這似乎是不可能得到的HTTP標頭,而無需下載完整的文件:如何在使用Ruby的OpenUri下載HTTP頭之前

open(base_url, 
    :content_length_proc => lambda {|t| 
    if t && 0 < t 
     pbar = ProgressBar.create(:total => t) 
    end 
    }, 
    :progress_proc => lambda {|s| 
    pbar.progress = s if pbar 
    }) {|io| 
    puts io.size 
    puts io.meta['content-disposition'] 
    } 

運行上面的代碼表明,它首先下載完整的文件,然後纔打印出我需要的頭。

有沒有一種方法可以在下載完整文件之前獲取標題,所以如果標題不是我期望的那樣,我可以取消下載?

+0

重複? http://stackoverflow.com/questions/13916046/display-http-headers-using-openuri?rq=1 – yeyo

+3

@Kira不,使用鏈接的答案將首先下載完整的文件,正是我不想要的。 – ePirat

回答

4

看來我想要的是不可能使用OpenURI,至少不是,正如我所說,沒有首先加載整個文件。

我能夠做什麼,我想使用的Net :: HTTP的request_get

下面的例子:

http.request_get('/largefile.jpg') {|response| 
    if (response['content-length'] < max_length) 
    response.read_body do |str| # read body now 
     # save to file 
    end 
    end 
} 

需要注意的是這隻能使用一個塊時,做它喜歡:

response = http.request_get('/largefile.jpg') 

身體已經被讀取。

+0

正確,OpenURI預先讀取內容,然後返回文件句柄,無論是否使用塊表單。 –

11

您可以使用Net :: HTTP對於這個問題,例如:

require 'net/http' 

http = Net::HTTP.start('stackoverflow.com') 

resp = http.head('/') 
resp.each { |k, v| puts "#{k}: #{v}" } 
http.finish 

另一個例子,這一次得到精彩的書的標題,對象編程東方符合ANSI-C

require 'net/http' 

http = Net::HTTP.start('www.planetpdf.com') 

resp = http.head('/codecuts/pdfs/ooc.pdf') 
resp.each { |k, v| puts "#{k}: #{v}" } 
http.finish 
+1

使用'start'的塊形式更清潔。請參閱[文檔]中的示例(http://ruby-doc.org/stdlib-2.0/libdoc/net/http/rdoc/Net/HTTP.html#method-i-head)。 –

+0

+1 @theTinMan。保持乾淨(鏈接到rdoc)。 – orde

+1

@theTinMan對不起,但這並不意味着我不知道這種形式的存在,因爲該參考鏈接提示。是的,如果使用塊形式,它會更乾淨,但並不意味着「完美」,有時縮進會變得太深或變得簡單,塊形式不適合,這取決於情況。 – yeyo

2

而不是使用Net :: HTTP,它可以像使用沙鏟在沙灘上挖一個池一樣,可以使用一些HTTP客戶端用於Ruby並清理代碼。

下面是使用HTTParty樣本:

require 'httparty' 

resp = HTTParty.head('http://example.org') 
resp.headers 
# => {"accept-ranges"=>["bytes"], "cache-control"=>["max-age=604800"], "content-type"=>["text/html"], "date"=>["Thu, 02 Mar 2017 18:52:42 GMT"], "etag"=>["\"359670651\""], "expires"=>["Thu, 09 Mar 2017 18:52:42 GMT"], "last-modified"=>["Fri, 09 Aug 2013 23:54:35 GMT"], "server"=>["ECS (oxr/83AB)"], "x-cache"=>["HIT"], "content-length"=>["1270"], "connection"=>["close"]} 

在這一點上很容易檢查文檔的尺寸:

resp.headers['content-length'] # => "1270" 

不幸的是,你在跟誰說話可能不知道如何在httpd大的內容將是;爲了快速響應,服務器不一定要計算動態生成輸出的大小,這需要幾乎一樣長的時間,並且幾乎與實際發送它的CPU密集程度相當,因此依賴「內容長度」值可能會出錯。

Net :: HTTP的問題是它不會自動處理重定向,所以你必須添加額外的代碼。當然,該代碼在文檔中提供,但代碼不斷增加,因爲您需要做更多的事情,直到您最終編寫另一個http客戶端(YAHC)。所以,避免這種情況,並使用現有的車輪。

+0

如果我正確理解了代碼,這實際上是一個HEAD請求,這不是我想要的,在這種情況下。儘管這可能是解決這個問題的好方法,但在這種情況下,我必須使用GET請求。 – ePirat

+0

GET將始終嘗試檢索整個文件。有可能進入處理過程並中止連接,但這不是一個好的網絡公民。考慮發生了什麼:您發出一個GET並且服務器加載文件以開始發送它。你放棄了,你剛剛在服務器和中間網絡以及你的主機上造成了額外的負擔。這就是HEAD被髮明的原因,爲了避免這樣做。 –

+0

正如我所說,我意識到這一點,但在具體的情況下HEAD沒有工作,所以GET是唯一的選擇。我想避免下載完整的文件只是爲了扔掉它,所以我認爲能夠儘快中止,而不是在下載整個文件之後中止,這將是一件好事。 – ePirat

相關問題