2012-10-09 16 views
6

Estoy usando jpegcam para permitir que un usuario tome una foto de webcam para establecer como su foto de perfil. Esta biblioteca termina la publicación de los datos en bruto a la Sever, que me sale en mi controlador de carriles de este modo:Cómo guardar una foto raw_data con paperclip

def ajax_photo_upload 
    # Rails.logger.info request.raw_post 
    @user = User.find(current_user.id) 
    @user.picture = File.new(request.raw_post) 

Esto no funciona y/paperclip rieles falla cuando intenta guardar request.raw_post.

Errno::ENOENT (No such file or directory - ????JFIF??? 

que he visto soluciones que hacen que un archivo temporal, pero tengo curiosidad de saber si hay una manera de conseguir Paperclip para guardar automáticamente el request.raw_post w/o tener que hacer un archivo temporal. ¿Alguna idea o solución elegante por ahí?

SOLUCIÓN FEO (Requiere un archivo temporal)

class ApiV1::UsersController < ApiV1::APIController 

    def create 
    File.open(upload_path, 'w:ASCII-8BIT') do |f| 
     f.write request.raw_post 
    end 
    current_user.photo = File.open(upload_path) 
    end 

private 

    def upload_path # is used in upload and create 
    file_name = 'temp.jpg' 
    File.join(::Rails.root.to_s, 'public', 'temp', file_name) 
    end 

end 

Esto es feo, ya que requiere un archivo temporal que se guardan en el servidor. ¿Consejos sobre cómo hacer que esto suceda sin que se guarde el archivo temporal? ¿Se puede usar StringIO?

+2

¿Te das cuenta de que usar FileSystem es una manera perfectamente válida de hacer las cosas bien? De hecho, el sistema Unix está basado casi en su totalidad en FileSystem, ese es el objetivo de por qué/dev/null existe. Una preocupación mucho más válida que tengo sobre esta solución es que es susceptible a una condición de carrera. –

+0

Estoy seguro de que es válido, pero crear un archivo significa que luego necesito un trabajo de cron para limpiar, borrar todos los archivos temporales, lo que, de no ser así, podría dar como resultado la clasificación de la HD y el bloqueo del servidor. ¿Por qué tener una cosa más de qué preocuparse? Estoy muy interesado en resolver esto elegantemente sin necesidad de un archivo temporal. ¿Menos partes móviles? – AnApprentice

+0

@AnApprentice, con los archivos antiguos de la clase 'Tempfile' limpiados por el recolector de basura. Ver mi respuesta a continuación. – Mischa

Respuesta

14

El problema con mi solución anterior era que el archivo temporal ya estaba cerrado y, por lo tanto, no podía ser utilizado por Paperclip. La solución a continuación funciona para mí. Es IMO la forma más limpia y (según la documentación) garantiza que los archivos temporales se eliminen después de su uso.

añade el siguiente método a su modelo User:

def set_picture(data) 
    temp_file = Tempfile.new(['temp', '.jpg'], :encoding => 'ascii-8bit') 

    begin 
    temp_file.write(data) 
    self.picture = temp_file # assumes has_attached_file :picture 
    ensure 
    temp_file.close 
    temp_file.unlink 
    end 
end 

controlador:

current_user.set_picture(request.raw_post) 
current_user.save 

No se olvide de añadir require 'tempfile' en la parte superior de su archivo User modelo.

+0

Gracias, pero la idea es no utilizar un archivo temporal – AnApprentice

+1

Luego tiene que hackear Paperclip para hacer lo que quiera o utilizar una biblioteca de procesamiento de archivos diferente que no requiera un archivo en el sistema de archivos. (¿Carrierwave?) De todos modos, esta solución es válida si le preocupa tener que limpiar archivos viejos, porque el recolector de basura lo hace por usted. ¿Qué otras preocupaciones tienes con los archivos temporales? – Mischa

+1

Por cierto, una carga de archivo normal crea un archivo temporal de forma similar a como lo hace este código. – Mischa

Cuestiones relacionadas