Как сохранить изображение base64 в Blob с Carrierwave в Rails4?


Как описано в этом учебнике, я преобразую холст в DataUrl, а этот DataUrl-в Blob. Затем я делаю запрос ajax post и хотел бы сохранить изображение в базе данных с помощью Carrierwave.

Это мой код JS:

uploadButton.on('click', function(e) {

  var dataURL = mycanvas.toDataURL("image/png;base64;");

  // Get our file
  var file= dataURLtoBlob(dataURL);

  // Create new form data
  var fd = new FormData();

  // Append our Canvas image file to the form data
  fd.append("image", file);

  // And send it
  $.ajax({
    url: "/steps",
    type: "POST",
    data: fd,
    processData: false,
    contentType: false,
  });
});

// Convert dataURL to Blob object
function dataURLtoBlob(dataURL) {

  // Decode the dataURL
  var binary = atob(dataURL.split(',')[1]);

  // Create 8-bit unsigned array
  var array = [];
  for(var i = 0; i < binary.length; i++) {
    array.push(binary.charCodeAt(i));
  }

  // Return our Blob object
  return new Blob([new Uint8Array(array)], {type: 'image/png'});
}

Когда я добавляю следующий код к своему контроллеру, то изображение сохраняется, но, конечно, не через carrierwave.

File.open("#{Rails.root}/public/uploads/somefilename.png", 'wb') do |f|
  f.write(params[:image].read)
end

Обновленная Информация:

Это парамы для моего поста ajax запрос:

Parameters: {"image"=>#<ActionDispatch::Http::UploadedFile:0x007feac3e9a8a8 @tempfile=#<Tempfile:/var/folders/0k/q3kc7bpx3_51kc_5d2r1gqcc0000gn/T/RackMultipart20140211-1346-gj7kb7>, @original_filename="blob", @content_type="image/png", @headers="Content-Disposition: form-data; name="image"; filename="blob"rnContent-Type: image/pngrn">}

И это параметры для стандартной загрузки файла:

Parameters: {"utf8"=>"✓", "image"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007feac20c2e20 @tempfile=#<Tempfile:/var/folders/0k/q3kc7bpx3_51kc_5d2r1gqcc0000gn/T/RackMultipart20140211-1346-1ui8wq1>, @original_filename="burger.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name="image[image]"; filename="xy.jpg"rnContent-Type: image/jpegrn">}}

Если я сделаю Image.create(params[:image]), у меня будет откат транзакции...

Ошибка отката транзакции:

Unprocessable Entity
ActiveRecord::RecordInvalid (Validation failed: image You are not allowed to upload "" files, allowed types: jpg, jpeg, gif, png)
2 8

2 ответа:

Вы вносите в белый список разрешенные типы файлов. По умолчанию Carrierwave попытается определить тип файла по расширению имени файла, которое не передается, так как это фактически объект Blob. Таким образом, вы получаете ошибку проверки о "типе" файла. Чтобы исправить это, просто добавьте ожидаемое расширение файла для объектов blob:

if params[:image].try(:original_filename) == 'blob'
  params[:image].original_filename << '.png'
end

Image.create!(image: params[:image])

Я просто хотел добавить, вы можете добавить тип файла в вашем представлении при добавлении вашего blob-объекта.

  // Get our file
  var file = dataURLtoBlob(dataURL);

  // Create new form data
  var fd = new FormData();

  // Append our Canvas image file to the form data
  fd.append("image", file, "blob.jpg");

Обратите внимание на окончание, когда мы определяем имя файла. Надеюсь, это кому-то поможет.

Источник: https://developer.mozilla.org/en-US/docs/Web/API/FormData/append