2012-11-15 41 views
8

我想通過這種方式來下載音樂文件:Ruby - 如何使用open-uri獲取文件的名稱?

require 'open-uri' 

source_url = "http://soundcloud.com/stereo-foo/cohete-amigo/download" 

attachment_file = "test.wav" 

open(attachment_file, "wb") do |file| 
    file.print open(source_url).read 
end 

在這個例子我想改變「Test.wav」到真正的文件名(例如像JDownloader程序一樣)。

編輯:我說的不是時間的文件,我的意思是像Jdownloader網絡存儲的文件獲得:「Cohete阿米戈 - 立體聲Foo.wav」

三江源閱讀

UPDATE :

我試過這個存儲的名稱:

attachment_file = File.basename(open(source_url)) 

我認爲沒有意義,但我不認識路要做到這一點,對不起。

回答

15

文件名存儲在名爲Content-Disposition的標題字段中。然而解碼這個領域可能有點棘手。看到一些討論,在此例如:

How to encode the filename parameter of Content-Disposition header in HTTP?

對於open-uri您可以通過meta訪問返回File類的訪問所有的頭字段:

f = open('http://soundcloud.com/stereo-foo/cohete-amigo/download') 
f.meta['content-disposition'] 
=> "attachment;filename=\"Stereo Foo - Cohete Amigo.wav\"" 

所以爲了解碼類似的東西你可以這樣做:

cd = f.meta['content-disposition']. 
filename = cd.match(/filename=(\"?)(.+)\1/)[2] 
=> "Stereo Foo - Cohete Amigo.wav" 

它適用於你的特定情況下,並且它也適用於引號"不存在。但是在更復雜的內容處理例如UTF-8文件名中,您可能會遇到一些麻煩。不知道使用UTF-8的頻率如何,即使soundcloud曾經使用過UTF-8。所以也許你不需要擔心(沒有確認或測試過)。

您也可以使用更先進的網絡抓取框架像Mechanize,並相信它做解碼爲您提供:

require 'mechanize' 

agent = Mechanize.new 
file = agent.get('http://soundcloud.com/stereo-foo/cohete-amigo/download') 
file.filename 
=> "Stereo_Foo_-_Cohete_Amigo.wav" 
+0

謝謝,你知道我是否可以檢索文件大小,而不必等待獲取文件的所有MB? – ElektroStudios

+0

查看內容長度標題。 – Danyel

6

File.basename(open(source_url))不會起作用,因爲open(source_url)返回一些的I/O處理排序,而不是像File.basename期望的字符串。

File.basename(source_url) 

將有更好的工作機會,除非該URL使用某種path/to/service/with/parameters/in/line/like/this類型編碼。

雖然Ruby的URI庫有幫助的有用工具。例如:

File.basename(URI.parse(source_url).path) 

將是一個起點。例如:

require 'uri' 

File.basename(URI.parse('http://www.example.com/path/to/file/index.html').path 
# => "index.html" 

和:

File.basename(URI.parse('http://www.example.com/path/to/file/index.html?foo=bar').path) 
# => "index.html" 

你知道,如果我能retreive文件大小也和怎麼樣?

一個偉大的方式在本地測試HTTP的東西,是運行在命令行gem server,讓寶石啓動一個小的web服務器提供的文件:

require 'open-uri' 

html_doc = open('http://0.0.0.0:8808/') do |io| 
    puts io.size 
    io.read 
end 

puts html_doc.size 

# => 114350 
# => 114350 

當你使用一個塊通過OpenURI的open命令,可以訪問塊變量中的很多連接信息,這是Tempfile類的一個實例。因此,您可以使用size找出傳入文件的大小。

這對小文件OK,但如果你是在一個大的文件拉着你可能要使用的Net :: HTTP發送head請求,這可能包括大小進行調查。我說可能是,因爲有時服務器不知道在動態內容的情況下會返回多少內容,或者CGI或子服務返回的內容無需說明。

使用「頭部」請求的好處是服務器不返回整個內容,只是頭部。所以,在過去,我已經使用head作爲前言發出請求,以查看我是否可以獲取所需的數據。如果不是的話,我會被迫使用正常的get來完整回覆。

+0

謝謝,你知道我是否可以檢索文件大小,以及如何? – ElektroStudios

+0

文件大小更難。它通常從服務器返回的HTTP頭中返回,並且可以通過Net :: HTTP的方法訪問。如果您使用帶有「open」的塊,其中一些可以在OpenURI的頭文件中找到。問題是,並非所有的請求都會導致Content-Length頭,因爲服務器不知道會返回多少。對於由某種類型的CGI生成的動態內容尤其如此。 –

+0

感謝您的信息 – ElektroStudios

相關問題