8

この方法で音楽ファイルをダウンロードしたい:

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が取得するようなWebに保存されたファイルを意味します:「Cohete Amigo - Stereo Foo.wav」

読んでくれてありがとう

アップデート:

名前を保存するためにこれを試しました:

attachment_file = File.basename(open(source_url))

意味がないと思いますが、やり方がわかりません、ごめんなさい。

4

2 に答える 2

19

ファイル名は、という名前のヘッダー フィールドに格納されますContent-Disposition。ただし、このフィールドのデコードは少し難しい場合があります。たとえば、ここでいくつかの議論を参照してください。

HTTPでContent-Dispositionヘッダーのファイル名パラメータをエンコードするには?

返されたクラスのアクセサーをopen-uri介してすべてのヘッダー フィールドにアクセスできます。metaFile

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 を使用するかどうかはわかりません。したがって、おそらくそれについて心配する必要はありません(確認もテストもされていません)。

のようなより高度な Web クロール フレームワークを使用して、Mechanizeそれを信頼してデコードを行うこともできます。

require 'mechanize'

agent = Mechanize.new
file = agent.get('http://soundcloud.com/stereo-foo/cohete-amigo/download')
file.filename
=> "Stereo_Foo_-_Cohete_Amigo.wav"
于 2012-11-15T09:05:01.013 に答える
5

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"

ファイルサイズも取得できるかどうか、またどのように取得できるか知っていますか?

HTTP をローカルでテストする優れた方法はgem server、コマンドラインから実行し、gem でドキュメント用の小さな 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

小さなファイルの場合は問題ありませんが、大きなファイルを取り込む場合は、Net::HTTP を使用して調査し、サイズが含まれている可能性がheadある要求を送信することをお勧めします。可能性があると言います。これは、動的コンテンツの場合、またはあえて言わない CGI またはサブサービスによって返されるコンテンツの場合、サーバーが返される量がわからない場合があるためです。

「head」リクエストを使用する利点は、サーバーがコンテンツ全体ではなくヘッダーのみを返すことです。headそのため、過去に、必要なデータを取得できるかどうかを確認するために、を使用してリクエストを開始しました。そうでない場合は、通常の を使用して完全な応答を取得する必要がありますget

于 2012-11-15T14:08:10.393 に答える