2012-11-15 5 views
8

나는이 방법으로 음악 파일을 다운로드하려면 :Ruby - open-uri로 파일 이름을 얻는 방법은 무엇입니까?

내가 실제 파일 이름에 "Test.wav"를 변경하려면 그 예에서
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 

(예 J 다운로더 (JDownloader) 프로그램의 경우와 같이).

편집 : 나는 임시 파일을 의미하지 않는다, 나는 J 다운로더 (JDownloader)와 같은 웹에 저장된 파일을 가져 의미 : "Cohete 아미고을 - 스테레오 Foo.wav"

UPDATE를 읽기

감사합니다를 : 그 아무 의미가 없다 생각

attachment_file = File.basename(open(source_url)) 

하지만 난 방법을 알고하지 않습니다

나는이 이름을 저장하기 위해 노력했습니다 죄송합니다.

답변

15

파일 이름은 Content-Disposition이라는 헤더 필드에 저장됩니다. 그러나이 필드를 디코딩하는 것은 약간 힘들 수 있습니다. 예를 들어 여기에 몇 가지 설명을 참조하십시오 : 그래서 그런 일을 디코딩하기 위해

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

:

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

open-uri 당신은 반환 File 클래스의 meta 접근을 통해 모든 헤더 필드에 액세스 할 수 있습니다 당신은 이것을 할 수 있었다 :

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" 
+0

감사합니다. 파일 크기를 모두 검색 할 수 있고 파일의 모든 MB를 기다리지 않고 확인할 수 있습니까? – ElektroStudios

+0

Content-length 헤더를 살펴보십시오. – Danyel

6

open(source_url) 일부의 I/O 핸들을 반환하기 때문에 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" 

내가 너무하는 방법과 파일 크기를 retreive 수 있는지 알 수 있습니까?

로컬 HTTP 물건을 테스트하는 좋은 방법은, 명령 줄에서 gem server을 실행하고 보석은 설명서의 내용에 대한 약간의 웹 서버를 불 수 있도록하는 것입니다 :

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을 사용하여 요청한 데이터를 얻을 수 있는지 알아 보았습니다. 그렇지 않은 경우 일반 응답 get을 사용하여 전체 응답을 보내야합니다.

+0

감사합니다. 파일 크기를 검색 할 수있는 방법을 알고 있습니까? – ElektroStudios

+0

파일 크기가 더 어렵습니다. 서버에서 반환 된 HTTP 헤더에서 반환되는 경우가 많으며 Net :: HTTP의 메서드를 통해 액세스 할 수 있습니다. 'open'을 가진 블록을 사용하면 OpenURI의 헤더에서 사용할 수 있습니다. 문제는 모든 요청이 Content-Length 헤더를 생성하지는 않는다는 것입니다. 왜냐하면 서버는 얼마나 많은 양이 돌아오고 있는지 알지 못하기 때문입니다. 그것은 일종의 CGI에 의해 동적 컨텐츠가 생성되는 경우 특히 그렇습니다. –

+0

감사 정보 – ElektroStudios

관련 문제