У меня есть файл base64 png, отправленный через параметры. Это base64, потому что он проходит через холст HTML5. Атрибут, через который он передается, является вложенным fields_for. Я не уверен, но это может препятствовать его сохранению? хотя сомневаюсь

Я попробовал самый популярный ответ: загрузка изображения Rails Carrierwave Base64

Это не помогло

Отличие в этом посте в том, что мой base64 выглядит так: "data:image/png;base64,iVvdvadGAqwete..."

Мой загрузчик:

class PrintFileUploader < CarrierWave::Uploader::Base

  include CarrierWave::MiniMagick

  storage :aws

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  class CarrierStringIO < StringIO
    attr_accessor :original_filename
    attr_accessor :content_type
  end
  version :canvas do
    process resize_to_fit: [1500, 1500]
  end

  def content_type_whitelist
    /image\//
  end

  def extension_whitelist
    %w(jpg jpeg png)
  end

end

Модель:

  mount_uploader :print_file, PrintFileUploader

  def image_data=(data)
    io = CarrierStringIO.new(base64.decode64(data))
    # self.mockup_image = io
    self.print_file = io
  end

Кажется, здесь ничего не происходит. Когда я проверяю запись, print_file равно nil

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

Как я могу взять свой base64 png, преобразовать его в носитель и отправить его в aws через носитель?

Попытки :

  def image_data=(data)
    data = data[(data.index(',') + 1)..-1]
    io = CarrierStringIO.new(base64.decode64(data))
    self.print_file = io
  end

Также попытался добавить data = data[(data.index(',') + 1)..-1] к content_type, просто чтобы попробовать.

Также попробовал это в моем загрузчике:

  before :cache, :convert_base64

  class CarrierStringIO < StringIO
    def original_filename
      # the real name does not matter
      "photo.png"
    end

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

  def convert_base64(file)
    if file.respond_to?(:original_filename) && file.original_filename.match(/^base64:/)
      fname = file.original_filename.gsub(/^base64:/, '')
      ctype = file.content_type
      decoded = Base64.decode64(file.read)
      file.file.tempfile.close!
      decoded = CarrierStringIO.new(decoded)
      decoded.original_filename = fname
      decoded.content_type = ctype
      file.__send__ :file=, decoded
    end
    file
  end

Нашел ^ это из других принятых ответов, но ни один из них, похоже, не работает.

На всякий случай, мой base64 png исходит из javascript с холста, например:

var url = canvas.toDataURL('image/png')
$("#canvascontent").val(url);

Поскольку < ... id="canvascontent" > является скрытым полем в форме.

0
uno 26 Окт 2019 в 10:34
Вы удаляете заголовок данных перед запуском decode64 для данных?
 – 
Casper
26 Окт 2019 в 19:33

1 ответ

Данные изображения кодируются в так называемой схеме data-uri. Этот формат имеет тип:

data:[<media type>][;base64],<data>

Прежде чем вы декодируете эти данные в base64, вам нужно удалить заголовок:

data = "data:image/png;base64,iVvdvadGAqwete...."

# Strip header
data = data[(data.index(',') + 1)..-1] 

# Decode
base64.decode64(data)

Или используйте гем URI данных:

uri = URI::Data.new(data)
uri.content_type # image/png
uri.data         # Base64 decoded data
1
Casper 26 Окт 2019 в 19:48
Хм, это имеет смысл. Добавил несколько своих попыток в пост. Может ли тот факт, что это передается как вложенное поле, повлиять на то, почему это не работает? Я знаю, что Carrwave настроен, так как я уже тестировал загрузку локальных файлов. Просто пытаюсь понять, почему ничего не происходит
 – 
uno
27 Окт 2019 в 09:52