Yo estoy usando el siguiente código para enviar el archivo en Rails.

si el Archivo.existen?(file_path) 
send_file(file_path, escriba: 'text/excel') 
Archivo.eliminar(file_path) 
final 

En esto estoy tratando de enviar el archivo y borrar el archivo desde el servidor una vez que se ha transmitido con éxito. Pero me estoy enfrentando cuestión es, la operación de eliminación es llegar ejecutado, mientras que el envío está realizando y debido a que yo no veo nada en el navegador.

Entonces, ¿hay alguna manera en Rails, una vez que el send_file se completa la operación de eliminar el archivo desde el servidor.

Cualquier ayuda sería muy apreciada.

Gracias,

Chetan

  • Yo no esto es posible en el interior del controlador de solicitud, y usted va a querer un retraso en el trabajo o un mecanismo similar para limpiar, lo que permite suficiente tiempo para que la descarga completa de las

3 Comentarios

  1. 38

    Porque estás usando send_file, Rieles pasará la solicitud junto a su servidor HTTP (nginx, apache, etc. – Ver los Rieles de la documentación en send_file con respecto a X-Sendfile encabezados). Debido a esto, cuando intenta eliminar el archivo, Rails no saber que está siendo utilizado.

    Puede intentar usar send_data lugar, que se bloqueará hasta que los datos se envían, lo que permite su File.delete solicitud para tener éxito. Tenga en cuenta que send_data requiere de un flujo de datos como su argumento, aunque, no es un camino, por lo que necesita para abrir el archivo primero:

    File.open(file_path, 'r') do |f|
      send_data f.read, type: "text/excel"
    end
    File.delete(file_path)

    La otra opción sería un trabajo de fondo que comprueba periódicamente los archivos temporales de eliminar.

    • También hay que tener en cuenta que send_data es probable que utilice más recursos para enviar el mismo contenido como send_file, pero no hay necesidad de obsesionarse acerca de la diferencia a menos que esto va a ser una gran característica del sitio.
    • Sí, para un archivo de texto básico que genera rápidamente no debería ser un gran problema. Pero para generar grandes/archivos lentos, un send_file + fondo de trabajo solución probablemente sería mejor.
    • Gracias Dylan para responder sobre este tema. Siguientes trabajó para mí: si Archivo.existen?(file_path) Archivo.abierto(file_path, ‘rb’) do |f| send_data f.lea, escriba: «application/excel», nombre de archivo: «file_name.xls» end end
    • Gracias Dylan para solución sencilla (y)
  2. 4

    Si usted está generando sobre la marcha el archivo que está intentando enviar, una solución es utilizar el Tempfile clase:

    begin
      # The second argument is optional:
      temp_file = Tempfile.new(filename, temp_directory)
    
      # ... edit temp_file as needed.
    
      # By default, temp files are 0600,
      # so this line might be needed depending on your configuration:
      temp_file.chmod(0644)
      send_file temp_file
    ensure
      temp_file.close
    end

    Contrario a lo que se indica en esta pregunta, esto funciona como se esperaba (el archivo permanece en el servidor el tiempo suficiente para ser servido, sino en última instancia, se elimina); este post parece indicar que esto es debido a actualizaciones en Rails 3.2.11, algo que he podido comprobar.

    • Estoy bastante seguro de que si usted desea realmente eliminar el tempfile, usted necesita para hacer algo como temp_file.desvincular
    • De acuerdo a la documentación, TempFile#cerrar con ningún parámetro termina llamando a #desvincular de forma automática, «cuando el objeto está finalizado». Funcionó como se esperaba de mí.
    • No cuento en este trabajo el 100% del tiempo. Se eliminará el archivo cuando el Tempfile es la recolección, y no hay garantías de que esto sucederá antes de que nginx/apache tiene abierto el archivo. Depende de la implementación interna de send_file en Rails. send_data es una mejor alternativa.
  3. 1

    Esto funciona para mí!
    Con send_data usted puede eliminar el archivo antes de enviar.

    file = File.open(Rails.root.join('public', 'uploads', filename), "rb")
    contents = file.read
    file.close
    
    File.delete(filepath) if File.exist?(filepath)
    
    send_data(contents, :filename => filename)

Dejar respuesta

Please enter your comment!
Please enter your name here