Загрузка изображений Rails Carrierwave Base64

Каков наилучший способ загрузки изображения с клиента в бэкэнд Rails с использованием Carrierwave. Сейчас наш разработчик iOS отправляет файлы в качестве base64, поэтому запросы поступают следующим образом:

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

Итак, мой вопрос - это действительно два вопроса. Должен ли я сказать ему отправить другой формат файла? Если base64 - это правильный способ отправки этих файлов, то как мне с ними работать в несущей?

Ответы

Ответ 1

Я думаю, что одним из решений может быть сохранение декодированных данных в файл, а затем назначение этого файла на установленный загрузчик. И после этого избавиться от этого файла.

Другое (в памяти) решение может быть следующим:

# 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 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

Ответ 2

Старый вопрос, но мне пришлось сделать аналогичную вещь, загрузите изображение из строки base64, которое было передано через запрос json. Это то, что я закончил:

#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

Ответ 3

Вы можете легко достичь этого, используя Carrierwave-base64 Gem, вам не нужно самостоятельно обрабатывать данные, все, что вы делаете, это добавить драгоценный камень и изменить свою модель из

mount_uploader :file, FileUploader

к

mount_base64_uploader :file, FileUploader

и вот, теперь вы можете легко сказать:

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