2012-11-15 8 views
8

Ich möchte eine Musikdatei auf diese Weise zum Download:Ruby - Wie bekomme ich den Namen einer Datei mit 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 

In diesem Beispiel möchte ich „test.wav“ der realen Dateinamen ändern (wie zum Beispiel JDownloader Programm der Fall ist).

EDIT: Ich habe die zeitliche Datei nicht meine, ich meine, wird die gespeicherte Datei im Web wie Jdownloader: "Cohete Amigo - Stereo Foo.wav"

Vielen Dank für

UPDATE gelesen :

ich habe versucht, diese die Namen zu speichern:

attachment_file = File.basename(open(source_url)) 

denke ich, dass kein Sinn hat, aber ich weiß nicht, die Art und Weise um es zu tun, sorry.

Antwort

15

Der Dateiname wird im Header-Feld Content-Disposition gespeichert. Das Entschlüsseln dieses Feldes kann jedoch ein wenig schwierig sein. Sehen Sie einige Diskussionen hier zum Beispiel:

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

Also, um so etwas zu entschlüsseln:

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

Für open-uri Sie alle Header-Felder durch die meta Accessor des zurück File Klasse zugreifen Sie könnten dies tun:

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

Es funktioniert für Ihre besonderen Fall, und es funktioniert auch, wenn die Anführungszeichen " nicht vorhanden sind. Aber in den komplexeren Fällen der Inhaltsdisposition wie UTF-8-Dateinamen könnten Sie in ein paar Schwierigkeiten geraten. Nicht sicher, wie oft UTF-8 verwendet wird und ob sogar Soundcloud UTF-8 verwendet. Vielleicht müssen Sie sich deswegen keine Sorgen machen (nicht bestätigt oder getestet).

Sie können auch eine erweiterte Web-Crawling verwenden Framework wie Mechanize und vertrauen sie die Decodierung für Sie zu tun:

require 'mechanize' 

agent = Mechanize.new 
file = agent.get('http://soundcloud.com/stereo-foo/cohete-amigo/download') 
file.filename 
=> "Stereo_Foo_-_Cohete_Amigo.wav" 
+0

danke, wissen Sie, ob ich die Dateigröße auch retreive und ohne zu warten, um alle mb der Datei zu bekommen? – ElektroStudios

+0

Schauen Sie sich den Inhalt-Länge-Header an. – Danyel

6

File.basename(open(source_url)) wird nicht funktionieren, weil open(source_url) gibt ein I/O-Griff einiger Sortierung, keine Zeichenfolge wie File.basename erwartet.

File.basename(source_url) 

würde eine bessere Chance Arbeits haben, es sei denn, die URL etwas path/to/service/with/parameters/in/line/like/this Typ-Codierung verwendet.

Ruby URI-Bibliothek verfügt über nützliche Tools, um hier zu helfen. Etwas wie:

File.basename(URI.parse(source_url).path) 

wäre ein Ausgangspunkt.Zum Beispiel:

require 'uri' 

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

und:

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

wissen Sie, wenn ich die Dateigröße retreive kann zu und wie?

Eine gute Möglichkeit, lokal HTTP Sachen zu testen, ist gem server von der Kommandozeile auszuführen, und lassen Sie Edelsteine ​​einen kleinen Web-Server für seine Dokumentation anwerfen:

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 

Wenn Sie einen Block verwenden Mit dem OpenURI-Befehl open erhalten Sie Zugriff auf viele Informationen über die Verbindung in der Blockvariablen, die eine Instanz der Klasse Tempfile ist. So können Sie die Größe der eingehenden Datei mit size herausfinden.

, die für kleine Dateien in Ordnung ist, aber wenn Sie in einer großen Datei ziehen Sie könnten mit Net untersuchen möchten :: HTTP eine head Anfrage zu senden, die könnte die Größe umfassen. Ich sage könnte, weil manchmal der Server nicht weiß, wie viel zurückgegeben wird, im Falle von dynamischen Inhalten, oder Inhalt wird von einem CGI oder Sub-Service, der nicht die Mühe zu sagen zurückgegeben.

Der Vorteil der Verwendung einer "Kopf" -Anforderung ist, dass der Server nicht den gesamten Inhalt zurückgibt, nur die Header. In der Vergangenheit habe ich also eine Anfrage mit head eingeleitet, um zu sehen, ob ich die benötigten Daten bekommen könnte. Wenn nicht, wäre ich gezwungen, die volle Antwort mit einem normalen get zu ziehen.

+0

danke, weißt du, ob ich die dateigröße auch retreien kann und wie? – ElektroStudios

+0

Dateigröße ist schwieriger. Es wird oft in den vom Server zurückgegebenen HTTP-Headern zurückgegeben und kann über die Net :: HTTP-Methoden aufgerufen werden. Einige davon sind in den Kopfzeilen von OpenURI verfügbar, wenn Sie einen Block mit 'open' verwenden. Das Problem ist, dass nicht alle Anfragen zu einem Content-Length-Header führen, da der Server nicht weiß, wie viel zurückkommt. Dies gilt insbesondere für dynamische Inhalte, die von einem CGI irgendeiner Art erzeugt werden. –

+0

danke für die info – ElektroStudios