2010-09-16 13 views
23

No puedo hacer que send_file (Model.attachment.path) funcione. No falla, sino que envía un archivo de 0 bytes al cliente, aunque los nombres de los archivos son correctos.Rails envía archivos de 0 bytes utilizando send_file

Este problema comenzó a suceder después de que hice una gran migración de los carriles 2.3.8 a 3.

Había un montón de otras cosas que tuvieron lugar en esta migración y yo haré todo lo posible a los detalles de todos ellos .

  1. Cambio de distribución/Cambio de servidor. Rackspace RHEL5 a linode Ubuntu 10.04LTS
  2. Rubí cambio de versión, 1.8.6 -> 1.9.2
  3. rieles cambio de versión, 2.3.8 -> 3.0.0
  4. httpd cambio de plataforma, apache2 -> nginx (Sin embargo Probé apache2 también y no funcionó).

que se trasladaron los archivos adjuntos a través de FTP, ya que no eran parte de mis repositorios Git para que se publicaron a través de implementar la tapa, en lugar de ftp manual a distancia (RHEL5) en local (Windows 7) y luego local (Windows 7) a distancia (Ubuntu10)

Sé que FTPing no retiene los permisos de archivo a través de las transferencias, entonces lo que también hice fue imitar los chmods que se vieron en mis servidores anteriores, por lo que son casi idénticos. (los usuarios/grupos son diferentes, configurados como root: root en lugar de olduser: olduser).

Un fragmento de la solicitud para descargar un archivo adjunto de mi registro de producción.

Started GET "/attachments/replies/1410?1277105698" for 218.102.140.205 at 2010-09-16 09:44:31 +0000 
    Processing by AttachmentsController#replies as HTML 
    Parameters: {"1277105698"=>nil, "id"=>"1410"} 
Sent file /srv/app/releases/20100916094249/attachments/replies/UE0003-Requisition_For_Compensation_Leave.doc (0.2ms) 
Completed 200 OK in 78ms 

Todo está bien. Permítanme también descartar problemas locales, he intentado descargar a través de Chrome tanto en Win7 como en Ubuntu (en Vbox).

Permítanme también asegurarles que la ruta es realmente correcta.

[email protected]:/srv/app/current# tail /srv/app/releases/20100916094249/attachments/replies/UE0003-Requisition_For_Compensation_Leave.doc 
# 
    # 
     %17nw 
       HQ��+1ae���� 
              %33333333333(��QR���HX�"%%��@9 
��@�p4��#[email protected]��Unknown������������G��z �Times New Roman5��Symbol3&� 
         �z �Arial5&� 

para resumir la pregunta, ¿cómo puedo obtener send_file para enviar realmente los archivos en lugar de falsa basura 0 bytes.

Respuesta

45

send_file tiene :x_sendfile parámetro que por defecto es true en Rails 3. Esta característica descarga la descarga de streaming al servidor front - Apache (con mod_xsendfile) o lighttpd, devolviendo respuesta vacía con cabecera X-Sendfile con la ruta.

Nginx utiliza X-Accel-Redirect cabecera para misma funcionalidad, pero hay que rieles configurar correctamente en el archivo de un lugar adecuado:

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' 

Rails 3 actualización: esta línea ya existe en production.rb, simplemente descomentarla.

Agregue sendfile on; a su configuración nginx para utilizar el encabezado enviado por Rails. Recuerde que se debe usar la ruta absoluta y nginx debe tener acceso de lectura al archivo.

Otra forma de archivos de alias:

Para una mayor seguridad en el uso de alias nginx en lugar de rutas absolutas, sin embargo send_file método comprueba la existencia del archivo, que falla con alias. Por lo tanto he cambiado de acción para:

head(
     'X-Accel-Redirect'=> file_item.location, 
     'Content-Type' => file_item.content_type, 
     'Content-Disposition' => "attachment; filename=\"#{file_item.name}\""); 
    render :nothing => true; 
+2

De hecho, descubrí la solución ayer y escribí sobre ella en el blog hoy http://www.novafist.com/2010/09/send_file-sends-0- bytes-to-client-in-rails/ – fivetwentysix

+2

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' es incluso mejor que head(). – gertas

+0

¡Gracias por la respuesta, me salvó bastante tiempo! –

18

En Rails 3, simplemente elimine la línea config.action_dispatch.x_sendfile_header = 'X-Accel-redirección' en production.rb dentro de los entornos de carpeta.

3

He tenido problemas similares con send_file() en el pasado, usando send_data() en su lugar me salvó en ese momento (por ejemplo, send_data File.read (filename),: disposition => 'inline',: type => " some/mimetype ")

+0

gracias por esto, ahórreme un montón de tiempo depurando porque no quería comentar la configuración. – covard

14

Sí, tuve el mismo problema con el X-sendfile habilitado por defecto también en Rails 3.

Si tiene gran volumen de llamadas "" send_file sólo se puede comentar de salida, la línea en config/ambientes/production.rb:

#config.action_dispatch.x_sendfile_header = "X-Sendfile" 

Entonces send_file método empezado a trabajar perfectamente.

Como no puedo instalar la extensión x-sendfile en Apache, solo busqué un poco y encontré esto.

Espero que ayude.

+0

En una instalación de Apache esto también solucionó mi problema inmediatamente. Bien encontrado –

0

en rieles 4, me doy cuenta de que mi problema es que eliminé el archivo temporal que he generado para enviar al usuario.

si no eliminé el archivo, send_file funciona. ive no probado en delgado pero funciona muy bien en el pasajero 5 como servidor independiente

Cuestiones relacionadas