Я хочу интегрировать Dropzone.js
с изменением размера изображения на стороне клиента. Я знаю, что есть функция изменения размера эскиза, но я бы хотел создать функцию изменения размера основного изображения перед загрузкой. Кто-нибудь может мне помочь, пожалуйста?
Dropzone.js + Изменение размера изображения на стороне клиента
Ответ 1
Вот как это сделать, не загружая файл из addedfile
.
Важно установить autoQueue
параметр false
, таким образом dropzone
не будет автоматически загружать файлы, выбранные пользователем.
var dropzone = new Dropzone (".dropzone", {
...
autoQueue: false,
...
});
Следующим шагом будет изменение размеров и изменение размеров в версии addedfile
.
dropzone.on("addedfile", function(origFile) {
var MAX_WIDTH = 800;
var MAX_HEIGHT = 600;
var reader = new FileReader();
// Convert file to img
reader.addEventListener("load", function(event) {
var origImg = new Image();
origImg.src = event.target.result;
origImg.addEventListener("load", function(event) {
var width = event.target.width;
var height = event.target.height;
// Don't resize if it small enough
if (width <= MAX_WIDTH && height <= MAX_HEIGHT) {
dropzone.enqueueFile(origFile);
return;
}
// Calc new dims otherwise
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
// Resize
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(origImg, 0, 0, width, height);
var resizedFile = base64ToFile(canvas.toDataURL(), origFile);
// Replace original with resized
var origFileIndex = dropzone.files.indexOf(origFile);
dropzone.files[origFileIndex] = resizedFile;
// Enqueue added file manually making it available for
// further processing by dropzone
dropzone.enqueueFile(resizedFile);
});
});
reader.readAsDataURL(origFile);
});
Здесь используется функция преобразования dataURL
в файл dropzone
. Процесс может быть проще, если вы используете canvas.toBlob() вместо canvas.toDataURL(), чтобы получить содержимое измененного файла, но последнее не поддерживается всеми браузерами.
Это просто измененная версия этой функции.
function base64ToFile(dataURI, origFile) {
var byteString, mimestring;
if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = decodeURI(dataURI.split(',')[1]);
}
mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0];
var content = new Array();
for (var i = 0; i < byteString.length; i++) {
content[i] = byteString.charCodeAt(i);
}
var newFile = new File(
[new Uint8Array(content)], origFile.name, {type: mimestring}
);
// Copy props set by the dropzone in the original file
var origProps = [
"upload", "status", "previewElement", "previewTemplate", "accepted"
];
$.each(origProps, function(i, p) {
newFile[p] = origFile[p];
});
return newFile;
}
Ответ 2
Документация Dropzone о функции изменения размера перед загрузкой сбивает с толку. Как это выглядит, вы можете либо ограничить ширину, ограничить высоту, либо ограничить и то и другое и пожертвовать соотношением сторон, исказив изображение. Это не вариант. Это:
resizeWidth: 1000, resizeHeight: 1000,
resizeMethod: 'contain', resizeQuality: 1.0,
Максимальная ширина или высота не должна превышать 1000 пикселей - в зависимости от того, что больше. Другой будет уменьшен в соответствии с соотношением сторон без искажения изображения. Так, например, в моем тесте я загрузил изображение размером 2688x1512. Dropzone обрезал и изменил размер миниатюры до значения по умолчанию 120x120, но файл, отправленный на сервер, был изменен с помощью Dropzone отдельно, до 1000x562, а затем отправлен на сервер.
Здесь есть интересная оговорка. JPEG файлы будут сжиматься с потерями, поэтому даже изменение размера до 1,0 приведет к потере. Я рассматриваю эту функцию как метод предотвращения чрезмерно больших файлов, но вы должны быть осторожны с изменением размера дважды, если можете избежать этого (один раз на сервере, один раз на клиенте).
Если вам этого недостаточно - и вы действительно хотели перегрузить метод transform - стоит отметить, что следование по пути кода внутри Dropzone немного сбивает с толку, поскольку createThumbnail
дорожка createThumbnail используется дважды при каждой загрузке, один раз для создания эскиза, подобного вы ожидаете, и снова предварительно изменить размер изображения здесь, прежде чем передавать его на сервер. Аналогично, метод resize
назван смущающе; в то время как resizeWidth и т.д. относятся к подготовке изображения к загрузке, resize относится к изменению размера миниатюры и никак не влияет на изображение, отправляемое на сервер.
Ответ 3
Это можно сделать, минуя загрузку, сделанную Dropzone.js. Для этого вам нужно установить autoQueue: false
в параметрах (как в пример загрузки).
Затем вы можете просто отправить миниатюру, или вы можете сделать это сложным способом.
Решение 1: Отправить эскиз
myDropzone.on('thumbnail', function(file, dataURL) {
$.post('http://example.com', {img: imgToSend})
})
Вы можете определить способ изменения размера/обрезки, добавив функцию изменения размера в параметры.
Решение 2: Изменить размер самостоятельно
Возникла и другая проблема: изображения нужно повернуть (это происходит очень часто). Для этого необходимо использовать тег ориентации EXIF. По-видимому, он теряется при изменении размера, поэтому вам нужно получить эту информацию в интерфейсе, прежде чем изменять размер. Для этого я использовал Exif.js library.
Вот рабочий пример на JSFiddle. Вы можете увидеть URI с измененным размером изображения в консоли.
Ответ 4
Недавно была выпущена версия 5 Dropzone, поэтому, если вы обновитесь до Dropzone 5, вы можете просто использовать resizeWidth и resizeHeigh, чтобы сжать изображение на стороне клиента.
Если вы предоставите только один из них, то dropzone будет учитывать исходное соотношение сторон, например, если вы просто добавите параметр: resizeWidth: 800
Тогда ваше изображение будет сжато до ширины = 800 пикселей, а исходное соотношение сторон изображения будет соблюдаться.
Ответ 5
Хорошо. Мне потребовалось некоторое время, а затем еще немного времени, чтобы найти, как реализовать изменение размера.
Вот окончательное решение, которое работает для меня:
Import css and dropzone.js
<div class="row">
<div class="col-sm-20 well">
<form action="@Url.Action("_UploadImages", "Notebooks", new { unique = Model.UniqueId })"
method="post"
enctype="multipart/form-data"
class="dropzone"
id="my-dropzone"></form>
</div>
</div>
<script type="text/javascript">
Dropzone.options.myDropzone = {
url: '@Url.Action("_UploadImages", "Notebooks", new { unique = Model.UniqueId })',
autoProcessQueue: true,
uploadMultiple: true,
parallelUploads: 3,
maxFilesize: 10,
resizeWidth: 2048,
addRemoveLinks: false,
init: function () {
}
}
</script>