2012-11-15 10 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 

その例では、私は(例えば同じようJDownloaderプログラムはありません)実際のファイル名に「Test.wav」を変更したいです。

EDIT:私は一時的なファイルを意味するものではありません、私はJdownloaderなどのWebに格納されたファイルが取得する意味: "coheteがアミーゴ - ステレオFoo.wav"

UPDATEを読むための

ありがとうを:

私は名前を保存するために、これを試してみた:

attachment_file = File.basename(open(source_url)) 

は、私はセンスがないのだと思うが、私は道を知りませんそれを行うには、申し訳ありません。

答えて

15

ファイル名は、Content-Dispositionというヘッダーフィールドに格納されます。しかし、このフィールドをデコードするのはちょっと難しいかもしれません。例えば、ここでいくつかの議論を参照してください:

open-uriについては

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

あなたが返さFileクラスのmetaアクセサを介してすべてのヘッダフィールドにアクセスすることができます:

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の使用頻度や、サウンドクラウドでさえUTF-8を使用しているかどうかは不明です。だから多分あなたはそれについて心配する必要はありません(確認もテストもしていません)。

ます。また Mechanizeなど、より高度なウェブクロールフレームワークを使用し、あなたのためのデコードを行うには、それを信頼でき

open(source_url)は、いくつかのI/Oハンドルを返すため

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

Content-lengthヘッダーを調べます。 – Danyel

6

File.basename(open(source_url))は動作しません。ソートは、File.basenameのような文字列ではありません。 URLは、いくつかのpath/to/service/with/parameters/in/line/like/thisタイプのエンコーディングを使用している場合を除き

File.basename(source_url) 

は、作業のよりよいチャンスを持っているでしょう。

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" 

知っていますか?

ローカル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を使用して調べることができます。

小さなファイルの場合は問題ありませんが、大きなファイルを取得する場合は、headリクエストを送信するためにNet :: HTTPを使用して調べることをおすすめします。にサイズが含まれている可能性があります。私はかもしれませんが、動的コンテンツの場合はどれだけ返されるか、言いたいことが気にしないCGIやサブサービスによって返されるコンテンツがどれくらいあるかをサーバが知らないことがあるので、

"ヘッド"リクエストを使用する利点は、サーバーがコンテンツ全体(ヘッダーのみ)を返さないことです。だから、これまでは、私が必要とするデータを得ることができるかどうかを確認するために、headを使ってリクエストを行うことになっていました。そうでない場合は、通常のgetを使用して完全な応答を引き出す必要があります。

+0

おかげさまで、私もファイルサイズを調べることができますか? – ElektroStudios

+0

ファイルサイズはより厳しくなります。これは、サーバから返されたHTTPヘッダで返されることが多く、Net :: HTTPのメソッドを介してアクセスできます。 'open'でブロックを使用すると、OpenURIのヘッダーで利用できるものがあります。問題は、サーバーがどれくらい戻ってくるのか分からないため、すべての要求がContent-Lengthヘッダーになるわけではありません。これは、何らかのCGIによって動的コンテンツが生成される場合に特に当てはまります。 –

+0

ありがとうございます。 – ElektroStudios