Ruby - 如何使用open-uri获取文件的名称?

Ele*_*ios 8 ruby url uri open-uri http

我想通过这种方式下载音乐文件:

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
Run Code Online (Sandbox Code Playgroud)

在该示例中,我想将"Test.wav"更改为真实文件名(例如JDownloader程序).

编辑:我不是指临时文件,我的意思是像Jdownloader这样的网络存储文件得到:"Cohete Amigo - Stereo Foo.wav"

谢谢你的阅读

更新:

我试过这个来存储这个名字:

attachment_file = File.basename(open(source_url))
Run Code Online (Sandbox Code Playgroud)

我认为这没有任何意义,但我不知道如何做到这一点,抱歉.

Cas*_*per 17

文件名存储在名为的头字段中Content-Disposition.但是解码这个字段可能有点棘手.请参阅此处的一些讨论:

如何在HTTP中编码Content-Disposition头文件名参数?

因为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\""
Run Code Online (Sandbox Code Playgroud)

所以为了解码这样的东西,你可以这样做:

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

它适用于您的特定情况,如果"不存在引号,它也可以工作.但在更复杂的内容处理案例中,如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"
Run Code Online (Sandbox Code Playgroud)

  • 查看 Content-length 标头内部。 (2认同)

the*_*Man 6

File.basename(open(source_url))将无法工作,因为open(source_url)返回某种类型的I/O句柄,而不是像File.basename期望的字符串.

File.basename(source_url)
Run Code Online (Sandbox Code Playgroud)

除非URL使用某种path/to/service/with/parameters/in/line/like/this类型的编码,否则将有更好的工作机会.

Ruby的URI库提供了有用的工具来帮助解决这个问题.就像是:

File.basename(URI.parse(source_url).path)
Run Code Online (Sandbox Code Playgroud)

将是一个起点.例如:

require 'uri'

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

和:

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

你知道我是否可以检索文件大小以及如何?

在本地测试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
Run Code Online (Sandbox Code Playgroud)

当您使用带有OpenURI open命令的块时,它使您可以访问块变量中有关连接的大量信息,这是Tempfile该类的一个实例.因此,您可以使用找出传入文件的大小size.

这对于小文件来说没问题,但是如果你要引入一个大文件,你可能想调查使用Net :: HTTP发送head请求,其中可能包括大小.我说可能,因为有时服务器不知道将返回多少,在动态内容的情况下,或由CGI或子服务返回的内容,如果没有说.

使用"head"请求的优点是服务器不返回整个内容,只返回标题.所以,在过去,我已经开始使用一个请求head,看看我是否可以获得我需要的数据.如果没有,我将被迫使用正常情况完全响应get.