Jaka jest różnica między send_data i send_file w Ruby on Rails?

79

Który z nich jest najlepszy do przesyłania strumieniowego i pobierania plików?

Proszę podać przykłady.

Pan Black
źródło

Odpowiedzi:

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

Główna różnica polega na tym, że przekazujesz DANE (kod binarny lub cokolwiek) za pomocą send_data lub file PATH za pomocą send_file .

Możesz więc wygenerować dane i wysłać je jako tekst w tekście lub jako załącznik bez generowania pliku na serwerze za pośrednictwem send_data . Lub możesz wysłać gotowy plik za pomocą send_file

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

Lub

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

Dla wydajności lepiej jest wygenerować plik raz, a następnie wysłać go tyle razy, ile chcesz. Więc send_filebędzie lepiej pasować.

W przypadku przesyłania strumieniowego, o ile rozumiem, obie te metody używają tych samych opcji i ustawień, więc możesz użyć X-Send lub cokolwiek innego.

UPD

send_data i zapisz plik:

data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_data( data )
fl00r
źródło
1
dzięki @ fl00r. Czy istnieje sposób, aby zapisać dane jako plik, a następnie wysłać, używając funkcji send_data? Ponieważ potrzebowałem kopii pliku na moim serwerze. Jak mogę to osiągnąć?
Mr. Black
W Twoim kodzie jest błąd: powinien { |f| f << data }.
True Soft
Cześć, zastanawiam się, czy ta odpowiedź jest nadal aktualna? Używam teraz Railsów 3.2.16 i send_filemusiałem użyć samego pliku, a nie ścieżki, aby działał. Chciałeś tylko zaktualizować na wypadek, gdyby inni to zetknęli?
FireDragon
20

send_file może być szybszy niż send_data

Jak wspomniałem fl00r , send_filepobiera ścieżkę i send_datadane.

Dlatego send_filejest to podzbiór send_data, ponieważ potrzebujesz pliku w systemie plików: możesz oczywiście po prostu przeczytać plik i użyć send_datana nim. Ale send_filemoże być szybszy, więc jest to kompromis między wydajnością a ogólnością.

send_filemoże być szybszy, ponieważ może wysłać X-Sendfilenagłówek na Apache ( X-Accel-Redirectna Nginx) zamiast zawartości pliku, ponieważ zna ścieżkę.

Ten nagłówek jest używany przez odwrotne proxy (Apache lub Nginx), które normalnie działa przed Railsami w konfiguracji produkcyjnej.

Jeśli X-Sendfilew odpowiedzi występuje, odwrotny serwer proxy ignoruje większość bieżącej odpowiedzi i tworzy nowy, który zwraca plik w podanej ścieżce.

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

Jest to znacznie wydajniejsze, ponieważ odwrotne proxy jest wysoce wyspecjalizowane w obsłudze plików statycznych i może to zrobić znacznie szybciej niż Railsy (które nie wysyłają danych pliku, jeśli X-Sendfilezostaną wysłane).

Typowym przypadkiem użycia send_filejest sytuacja, gdy chcesz kontrolować prawa dostępu do plików statycznych: nie możesz ich /publicprzypisać, bo inaczej zostałyby obsłużone, zanim Railsy miałyby szansę zdecydować. Jest to omówione w: Ochrona zawartości publicznej / w aplikacji Railsowej

Aby skorzystać z X-Sendfilenagłówków, musisz dodać:

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

do config/initializers/production.rb(lub config/environment/production.rbw Railsach 5.x), nie application.rb , ponieważ w fazie rozwoju nie masz serwera proxy i chcesz send_filefaktycznie wysłać dane.

X-Sendfilejest omówione w przewodniku po strukturze aktywów .

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło