我想将 Dropzone.js
与客户端图像调整集成。我知道有一个函数可以调整缩略图的大小,但我想创建一个函数,在上传之前调整主图像的大小。请问有人能帮助我吗?
我想将 Dropzone.js
与客户端图像调整集成。我知道有一个函数可以调整缩略图的大小,但我想创建一个函数,在上传之前调整主图像的大小。请问有人能帮助我吗?
以下是如何在不从addedfile
上传文件的情况下完成操作。
重要的事情是将autoQueue
选项设置为false
,这样dropzone
就不会自动上传用户选择的文件。
var dropzone = new Dropzone (".dropzone", {
...
autoQueue: false,
...
});
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's 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;
}
Dropzone关于预上传调整大小功能的文档很令人困惑。它的阅读方式似乎是,您可以限制宽度、限制高度或两者兼而有之,并牺牲纵横比,从而扭曲图像。但事实并非如此。以下是正确的:
resizeWidth: 1000, resizeHeight: 1000,
resizeMethod: 'contain', resizeQuality: 1.0,
这里有一个有趣的警告。JPEG将被重新压缩,且会有损失,因此即使resizeQuality为1.0,也会导致损失。我认为这个功能是防止文件过大的一种方法,但如果可以避免,您应该小心不要重复调整大小(在服务器和客户端上各一次)。
如果这还不够用 - 而你真的想要超载transform方法 - 值得注意的是,跟随Dropzone内部代码路径有点混乱,因为createThumbnail代码路径每次上传都会使用两次,一次创建缩略图,一次在此之前对图像进行预缩放,然后将其传递给服务器。同样,resize方法的命名令人困惑;虽然resizeWidth等指的是为上传准备图像,但resize指的是为缩略图调整大小,并不影响发送到服务器的图像。
最近发布了Dropzone 5版本,如果您升级到Dropzone 5,则可以在客户端使用resizeWidth
和resizeHeigh
来压缩图像。
如果您只提供其中一个参数,那么Dropzone将会保持原始纵横比例。例如,如果您只添加选项:resizeWidth: 800
,则您的图像将被压缩为width=800
像素,并且您原始图像的纵横比例将得到保留。
autoQueue: false
(如Bootstrap示例中所示)。myDropzone.on('thumbnail', function(file, dataURL) {
$.post('http://example.com', {img: imgToSend})
})
您可以通过在选项中添加“resize”函数来定义调整大小/裁剪的方式。
还有另一个问题:图像可能需要旋转(这经常发生)。为此,必须使用EXIF方向标记。当您调整大小时,该标记似乎会丢失,因此您必须在前端获取此信息,然后再调整大小。为此,我使用了Exif.js库。
这里是JSFiddle上的工作示例。您可以在控制台中查看调整大小后的图像数据URI。
好的,花了我一些时间才找到如何实现调整大小。
这是最终的解决方案,适用于我:
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>