Ruby Shrine - обрезка и прямая загрузка сафари
Я реализую прямую загрузку с Shrine, jquery.fileupload и cropper.js
в части добавления я загружаю изображение из файла загрузки в модал, определяю обрезку и показываю модал
if (data.files && data.files[0]) {
var reader = new FileReader();
var $preview = $('#preview_avatar');
reader.onload = function(e) {
$preview.attr('src', e.target.result); // insert preview image
$preview.cropper({
dragMode: 'move',
aspectRatio: 1.0 / 1.0,
autoCropArea: 0.65,
data: {width: 270, height: 270}
})
};
reader.readAsDataURL(data.files[0]);
$('#crop_modal').modal('show', {
backdrop: 'static',
keyboard: false
});
}
Затем, нажав на модальную кнопку, я получаю вызов обрезанного холста на Blob и отправляю на S3.
$('#crop_button').on('click', function(){
var options = {
extension: data.files[0].name.match(/(\.\w+)?$/)[0], // set extension
_: Date.now() // prevent caching
};
var canvas = $preview.cropper('getCroppedCanvas');
$.getJSON('/images/cache/presign', options).
then(function (result) {
data.formData = result['fields'];
data.url = result['url'];
data.paramName = 'file';
if (canvas.toBlob) {
canvas.toBlob(
function (blob) {
var file = new File([blob], 'cropped_file.jpeg');
console.log('file', file);
data.files[0] = file;
data.originalFiles[0] = data.files[0];
data.submit();
},
'image/jpeg'
);
}
});
});
После завершения загрузки на S3 я записываю атрибуты изображения в скрытое поле, закрывая модальный режим и уничтожая обрезку
done: function (e, data) {
var image = {
id: data.formData.key.match(/cache\/(.+)/)[1], // we have to remove the prefix part
storage: 'cache',
metadata: {
size: data.files[0].size,
filename: data.files[0].name.match(/[^\/\\]*$/)[0], // IE returns full path
// mime_type: data.files[0].type
mime_type: 'image/jpeg'
}
};
console.log('image', image);
$('.cached-avatar').val(JSON.stringify(image));
$('#crop_modal').modal('hide');
$('#preview_avatar').cropper('destroy');
}
С хромом все работало нормально с самого начала, но потом я понял, что у сафари нет функциональности toBlob.
Я нашел это:
https://github.com/blueimp/JavaScript-Canvas-to-Blob И toBlob не является ошибкой функции исчезла..
Теперь я не могу сохранить изображение из-за проблемы, связанной с типом пантомимы.
Мне удалось выяснить точное местоположение, где это терпит неудачу на сафари, но не хром.
define_mime_type.rb строка 142
по линии 139 в options = {stdin_data: io.read(MAGIC_NUMBER), binmode: true}
stdin_data пусто после io.read
Есть идеи?
Спасибо!
ОБНОВИТЬ
Я смог выяснить, что URL к кэшированному изображению возвращается
$.getJSON('/images/cache/presign', options)
возвращает пустой файл, когда обрезается и загружается из сафари.
1 ответ
Так как я упоминал в вопросе, сафари загрузил пустой файл, как только он был обрезан cropper.js.
Проблема явно возникла из этого блока:
if (canvas.toBlob) {
canvas.toBlob(
function (blob) {
var file = new File([blob], 'cropped_file.jpeg');
console.log('file', file);
data.files[0] = file;
data.originalFiles[0] = data.files[0];
data.submit();
},
'image/jpeg'
);
}
В некоторых комментариях к одной из статей, которые я прочитал, я обнаружил, что safari выполняет что-то вроде file.toString, что в моем случае приводит к загрузке пустого файла.
Я добавил блоб напрямую, не создавая файл из него, и все работало нормально.
if (canvas.toBlob) {
canvas.toBlob(
function (blob) {
data.files[0] = blob;
data.files[0].name = 'cropped_file.jpeg';
data.files[0].type = 'image/jpeg';
data.originalFiles[0] = data.files[0];
data.submit();
},
'image/jpeg'
);
}