Was ist der Unterschied zwischen send_data und send_file in Ruby on Rails?

79

Welches eignet sich am besten für Streaming und Dateidownloads?

Bitte geben Sie Beispiele an.

Herr Schwarz
quelle

Antworten:

109
send_data(_data_, options = {})
send_file(_path_, options = {}) 

Der Hauptunterschied besteht darin, dass Sie DATA (Binärcode oder was auch immer) mit send_data oder file PATH mit send_file übergeben .

Sie können also einige Daten generieren und als Inline-Text oder als Anhang senden, ohne über send_data eine Datei auf Ihrem Server zu generieren . Oder Sie können eine fertige Datei mit send_file senden

data = "Hello World!"
send_data( data, :filename => "my_file.txt" )

Oder

data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_file( file )

Aus Leistungsgründen ist es besser, eine Datei einmal zu generieren und sie dann so oft zu senden, wie Sie möchten. So send_filewird besser passen.

Soweit ich weiß, verwenden beide Methoden für das Streaming die gleichen Optionen und Einstellungen, sodass Sie X-Send oder was auch immer verwenden können.

UPD

send_data und Datei speichern:

data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_data( data )
fl00r
quelle
1
danke @ fl00r. Gibt es eine Möglichkeit, die Daten als Datei zu speichern und dann mit der Funktion send_data zu senden? Weil ich eine Kopie der Datei auf meinem Server brauchte. Wie kann ich das erreichen?
Mr. Black
Es gibt einen Fehler in Ihrem Code: Es sollte sein { |f| f << data }.
True Soft
Hallo, ich frage mich, ob diese Antwort noch relevant ist? Ich verwende jetzt Rails 3.2.16 und send_filemusste die Datei selbst verwenden, nicht den Pfad, damit sie funktioniert. Wollten Sie nur aktualisieren, falls andere darauf stoßen?
FireDragon
20

send_file ist möglicherweise schneller als send_data

Wie bereits erwähnt , send_filenimmt fl00r einen Pfad und send_datadie Daten.

Daher send_fileist eine Teilmenge von send_data, da Sie eine Datei im Dateisystem benötigen: Sie können die Datei natürlich einfach lesen und darauf verwenden send_data. Aber send_filekann schneller sein, so ist es eine Leistung / Allgemeinheit trade-off ist.

send_filekann schneller sein, weil es den X-SendfileHeader auf Apache ( X-Accel-Redirectauf Nginx) anstelle des Dateiinhalts senden kann , da es den Pfad kennt.

Dieser Header wird vom Reverse-Proxy (Apache oder Nginx) verwendet, der normalerweise in einem Produktions-Setup vor Rails ausgeführt wird.

Wenn X-Sendfiledie Antwort vorhanden ist, ignoriert der Reverse-Proxy den größten Teil der aktuellen Antwort und erstellt eine neue, die die Datei unter dem angegebenen Pfad zurückgibt.

Client <---> Internet <---> Reverse proxy <---> Rails

Dies ist viel effizienter, da der Reverse-Proxy hochspezialisiert auf die Bereitstellung statischer Dateien ist und dies viel schneller als Rails kann (der die Dateidaten nicht sendet, wenn X-Sendfilesie gesendet werden).

Der typische Anwendungsfall send_fileist, wenn Sie die Zugriffsberechtigung für statische Dateien steuern möchten: Sie können sie nicht ablegen, da sie /publicsonst bereitgestellt werden, bevor Rails die Möglichkeit hat, sich zu entscheiden. Dies wird unter folgender Adresse erläutert: Schutz des Inhalts von public / in einer Rails-App

Um die X-SendfileHeader verwenden zu können, müssen Sie Folgendes hinzufügen:

config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx

an config/initializers/production.rb(oder config/environment/production.rbin Rails 5.x) nicht application.rb , da Sie in der Entwicklung keinen Proxyserver haben und send_filedie Daten tatsächlich senden möchten .

X-Sendfilewird im Asset Pipeline-Handbuch erläutert .

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle