我想通过这种方式下载音乐文件:
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 Amigo - Stereo Foo.wav”
谢谢你的阅读
更新:
我试过这个来存储名称:
attachment_file = File.basename(open(source_url))
我认为这没有任何意义,但我不知道如何做到这一点,抱歉。
答案 0 :(得分:15)
文件名存储在名为Content-Disposition
的标题字段中。但是解码这个字段可能有点棘手。请参阅此处的一些讨论:
How to encode the filename parameter of Content-Disposition header in HTTP?
对于open-uri
,您可以通过返回的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
,并相信它可以为您解码:
require 'mechanize'
agent = Mechanize.new
file = agent.get('http://soundcloud.com/stereo-foo/cohete-amigo/download')
file.filename
=> "Stereo_Foo_-_Cohete_Amigo.wav"
答案 1 :(得分: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"
你知道我是否可以检索文件大小以及如何?
在本地测试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
提取完整的回复。