2013-02-15 5 views
15

Qual è il modo migliore per caricare un'immagine da un client a un back-end Rails utilizzando Carrierwave. In questo momento il nostro sviluppatore iOS proietta i file come Base64, così le richieste vengono in questo modo:Rails Carrierwave Base64 caricamento immagine

"image_data"=>"/9j/4AAQSkZJRgABAQAAAQABAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAHqADAAQAAAABAAAAHgAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAAeAB4DAREAAhEBAxEB/8QAHwAAAQUBAQE.... 

Così, la mia domanda è in realtà due domande. Devo dirgli di inviare un diverso formato di file? Se base64 è il modo giusto per inviare questi file, come faccio a gestirli in carrierwave?

+0

L'app iOS non è in grado di inviare una richiesta POST di caricamento file multipart standard? – Tomdarkness

+0

onestamente non ne sono sicuro. non codifico in iOS – botbot

+0

Neanche io, ma chiederei al tuo sviluppatore iOS se questo è possibile visto che dal punto di vista di Rails sembra l'opzione più ragionevole piuttosto che trattare con i dati codificati base_64. – Tomdarkness

risposta

26

Penso che una soluzione possa essere quella di salvare i dati decodificati in un file e quindi assegnare questo file all'uploader montato. E dopo si sbarazzarsi di quel file.

L'altra soluzione (in memoria) può essere questa:

# define class that extends IO with methods that are required by carrierwave 
class CarrierStringIO < StringIO 
    def original_filename 
    # the real name does not matter 
    "photo.jpeg" 
    end 

    def content_type 
    # this should reflect real content type, but for this example it's ok 
    "image/jpeg" 
    end 
end 

# some model with carrierwave uploader 
class SomeModel 
    # the uploader 
    mount_uploader :photo, PhotoUploader 

    # this method will be called during standard assignment in your controller 
    # (like `update_attributes`) 
    def image_data=(data) 
    # decode data and create stream on them 
    io = CarrierStringIO.new(Base64.decode64(data)) 

    # this will do the thing (photo is mounted carrierwave uploader) 
    self.photo = io 
    end 

end 
+0

lo proverò sicuramente, grazie all'uomo – botbot

+0

sono curioso di sapere quale sarebbe la soluzione non in memoria? dovrei avere dubbi sulle prestazioni con questa soluzione? – botbot

+0

come si chiamerebbe image_data = (data)? – botbot

4

vecchia questione, ma ho dovuto fare una cosa simile, caricare un'immagine dalla stringa Base64 che è stata trasmessa attraverso una richiesta JSON. Questo è quello che ho finito per fare:

#some_controller.rb 
def upload_image 
    set_resource 
    image = get_resource.decode_base64_image params[:image_string] 
    begin 
    if image && get_resource.update(avatar: image) 
     render json: get_resource 
    else 
     render json: {success: false, message: "Failed to upload image. Please try after some time."} 
    end 
    ensure 
    image.close 
    image.unlink 
    end 
end 

#some_model.rb 
def decode_base64_image(encoded_file) 
    decoded_file = Base64.decode64(encoded_file) 
    file = Tempfile.new(['image','.jpg']) 
    file.binmode 
    file.write decoded_file 

    return file 
end 
0

si può facilmente raggiungere questo usando Carrierwave-base64 Gem non c'è bisogno di gestire i dati da soli, tutto ciò che fai è aggiungere la gemma e cambiare il proprio modello da

mount_uploader :file, FileUploader 

a

mount_base64_uploader :file, FileUploader 

e questo è tutto, ora si può facilmente dire:

Attachment.create(file: params[:file])