2010-12-09 6 views
2

Ich schreibe eine Rails-Anwendung, die Dateien auf einem Remote-Server für den Endbenutzer bereitstellt.Alternative zu X-sendfile in Apache für das Senden von Datei mit einer URL?

In meinem Fall werden die Dateien auf S3 gespeichert, aber der Benutzer fragt die Datei über die Rails-Anwendung an (die tatsächliche URL wird ausgeblendet). Wenn sich die Datei auf dem lokalen Dateisystem meines Servers befand, konnte ich den Apache-Header X-Sendfile verwenden, um den Ruby-Prozess für andere Anfragen freizugeben, während Apache die Aufgabe übernahm, die Datei an den Client zu senden. Aber in meinem Fall - wo die Datei nicht auf dem lokalen Dateisystem ist, sondern auf S3 - scheint es, dass ich gezwungen bin, sie vorübergehend in Rails herunterzuladen, bevor ich sie an den Client sende.

Gibt es keine Möglichkeit für Apache, eine "Remote" -Datei an den Client zu senden, die sich nicht auf dem Server selbst befindet? Es macht mir nichts aus, wenn Apache die Datei herunterladen muss, damit das funktioniert, solange ich den Ruby-Prozess nicht binden muss, solange er läuft.

Irgendwelche Vorschläge?

+0

Sie müssen etwas Ruby-Zeug vor dem Senden der Datei tun? Sie können nicht einfach die URL neu schreiben, müssen Sie die S3 URL verstecken?Nur um zu klären –

+0

Nicht wirklich, aber ich habe zwei Anforderungen: 1) Ich möchte den Download in einem Protokoll aufzeichnen (das ist nicht möglich, wenn der Client die Datei direkt von S3 anfordert). 2) Ich möchte, dass der Benutzer-Browser fragt, die Datei zu speichern, anstatt sie im Browser-Fenster anzuzeigen (heute verwende ich den Header "Content-Disposition: Anhang"). Ich weiß nicht, ob es möglich ist, S3-Links zum Herunterladen als Anhang zu zwingen, anstatt es inline anzuzeigen. –

Antwort

0

Thomas, ich habe ähnliche Anforderungen/Probleme und ich denke, ich kann dein Problem beantworten. Zuerst (und ich bin nicht 100% sicher, dass du dich für diesen Teil interessierst), ist das Ausblenden der S3-URL ziemlich einfach, da Amazon dir erlaubt, CNAMES auf deinen Bucket zu verweisen und eine benutzerdefinierte URL anstelle der Amazon-URL zu verwenden. Um dies zu tun, müssen Sie Ihr DNS auf die richtige Amazon-URL verweisen. Als ich meins aufstellte, war es ähnlich: files.domain.com zeigt auf files.domain.com.s3.amazonaws.com. Dann müssen Sie den Bucket mit dem Namen Ihrer benutzerdefinierten URL (files.domain.com in diesem Beispiel) erstellen. Wie man diese URL anruft, hängt davon ab, welches Juwel Sie verwenden, aber ein Wort der Warnung war, dass das von mir verwendete attachment_fu-Plugin mich fälschlicherweise an files.domain.com/files.domain.com/name_of_file schickte .... Ich konnte die Einstellung nicht finden, um es zu beheben, so dass eine einfache .sub-Methode für den S3-Teil des Plugins es reparierte.

On zu Ihren anderen Fragen, einige Schienen-Code (wie die Aufzeichnung der Treffer in der db) auszuführen, bevor Sie dies einfach tun Download:

def download 
    file = File.find(... 
    # code to record 'hit' to database 
    redirect_to 3Object.url_for(file.filename, 
           bucket, 
           :expires_in => 3.hours) 
end 

Dieser Code wird immer noch die Datei bedient werden verursachen, indem sie S3, aber und noch geben Sie die Fähigkeit, etwas Rubin zu laufen. (Natürlich funktioniert der obige Code nicht so wie er ist, Sie müssen ihn auf die richtige Datei und den Bucket verweisen und meine Amazon-Schlüssel werden in einer Konfigurationsdatei gespeichert. Das obige verwendet auch die Syntax für das AWS :: S3-Juwel - http://amazon.rubyforge.org/).

Zweitens ist die Problematik der Content-Disposition: Attachment etwas komplizierter. Hoffentlich ist Ihre Situation ein bisschen einfacher als meine und die folgende Lösung kann funktionieren. Unter der Annahme, das Objekt ‚Datei‘ (in diesem Beispiel) wird das richtige S3-Objekt, können Sie die Disposition zur Befestigung gesetzt durch

file.content_disposition = "attachment" 
file.save 

Der obigen Code kann ausgeführt werden, nachdem die Datei auf dem Server S3 vorhanden ist (im Gegensatz zu einigen anderen Header und Berechtigungen), das ist nett und es kann auch hinzugefügt werden, wenn Sie die Datei hochladen (Syntax hängt von Ihrem Plugin ab). Ich versuche immer noch, einen Weg zu finden, S3 zu sagen, es als Anhang zu senden und nur auf Anfrage (nicht jedes Mal), und wenn Sie das finden, lassen Sie mich bitte Ihre Lösung wissen. Ich muss in der Lage sein, es manchmal herunterzuladen und andere Zeiten zu speichern, um Bilder (zum Beispiel) in HTML einzubetten. Ich benutze nicht die oben erwähnte Weiterleitung, aber zum Glück scheint es, dass wenn Sie (wie ein HTML-Bild-Tag) eine Datei mit dem Content-disposition/attachment-Header einbetten, und der Browser das Bild normal anzeigt (aber ich nicht gründlich getestet, dass über genügend Browser, um es in der Wildnis zu senden).

Hoffe, dass hilft! Viel Glück.

+0

Ich habe herausgefunden, dass Sie in Amazon S3 benutzerdefinierte Header für jede Datei festlegen können. Dies bedeutet, dass Sie beim Speichern der Datei in S3 einfach einen Content-Disposition-Header festlegen können. Sie können sehen, wie ich es hier geschafft habe: https://gist.github.com/798393 –

+0

Dank Thomas, habe ich auch herausgefunden, dass ich keine benutzerdefinierten Header für jede Datei festlegen kann, sondern auch festgestellt, dass Sie den Inhalt festlegen können -Disposition Header beim Speichern, musste es aber noch implementieren. Ich werde mir deinen Code ansehen. –

Verwandte Themen