2013-02-15 19 views
15

Jaki jest najlepszy sposób na przesłanie obrazu z klienta do backendu Railsowego za pomocą Carrierwave. W tej chwili nasz programista iOS wysyła pliki jako base64, więc żądania przychodzą w ten sposób:Rails Carrierwave Base64 upload obrazu

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

Moje pytanie to naprawdę dwa pytania. Czy powinienem mu powiedzieć, żeby wysłał inny format pliku? Jeśli base64 jest właściwą metodą wysyłania tych plików, to jak sobie z nimi radzić w trybie operatora?

+0

Czy aplikacja iOS nie może wysłać żądania POST standardowego wysyłania pliku wieloczęściowego? – Tomdarkness

+0

Szczerze mówiąc, nie jestem tego pewien. Nie koduję w systemie iOS – botbot

+0

Ja też, ale pytam twojego programistę na iOS, czy jest to możliwe, z punktu widzenia Railsa, wydaje się to raczej rozsądną opcją niż przetwarzaniem zakodowanych danych base_64. – Tomdarkness

Odpowiedz

26

Myślę, że jednym z rozwiązań może być zapisanie zdekodowanych danych do pliku, a następnie przypisanie tego pliku do podłączonego uploadera. A potem pozbądź się tego pliku.

Innym rozwiązaniem (w pamięci) może być to jedno:

# 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

zdecydowanie spróbuję tego, dzięki człowieku – botbot

+0

Jestem ciekawy, co by nie było rozwiązaniem w pamięci? Czy powinienem mieć obawy dotyczące wydajności tego rozwiązania? – botbot

+0

jak nazwałbym image_data = (dane)? – botbot

4

Stare pytanie, ale musiałem zrobić coś podobnego, przesłać obraz z base64 ciąg, który został przekazany na żądanie za pomocą JSON. To, co skończyło się robi:

#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

można łatwo osiągnąć stosując Carrierwave-base64 Gem nie trzeba obsłużyć dane samodzielnie, wszystko co musisz zrobić to dodać gem i zmienić swój model z

mount_uploader :file, FileUploader 

do

mount_base64_uploader :file, FileUploader 

i to wszystko, teraz można łatwo powiedzieć:

Attachment.create(file: params[:file]) 
Powiązane problemy