Dropzone.js + redimensionnement de L'Image côté Client
je veux intégrer le Dropzone.js avec un redimensionnement de L'Image côté Client. Je sais qu'il y a une fonction pour redimensionner la miniature, mais je voudrais créer une fonction pour redimensionner l'image avant de le télécharger. Quelqu'un pourrait m'aider s'il vous plaît?
5 réponses
Voici comment le faire sans télécharger le fichier de addedfile
.
L'Important est de mettre autoQueue
option false
,dropzone
pas de téléchargement automatique des fichiers sélectionnés par l'utilisateur.
var dropzone = new Dropzone (".dropzone", {
...
autoQueue: false,
...
});
la prochaine étape est de faire redimensionner et de rechercher des versions redimensionnées dans addedfile
événement.
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);
});
Voici une fonction pour convertir dataURL
dropzone
fichier. Le processus pourrait être plus simple si vous utilisez toile.toBlob () au lieu de toile.toDataURL (), pour obtenir le contenu du fichier redimensionné, mais ce dernier n'est pas bien supporté par tous les navigateurs.
C'est juste une version modifiée de la fonction.
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;
}
la documentation de Dropzone sur la fonctionnalité de redimensionnement du pré-téléchargement est déroutante. La façon dont il lit, vous pouvez soit limiter la largeur, limiter la hauteur, ou limiter les deux et sacrifier le rapport D'Aspect, déformant l'image. Ce n'est pas le cas. Ceci:
resizeWidth: 1000, resizeHeight: 1000,
resizeMethod: 'contain', resizeQuality: 1.0,
limites largeur ou hauteur jusqu'à un maximum de 1000px-la plus grande des deux valeurs étant retenue. L'autre sera réduit en accord avec le rapport D'Aspect, sans déformer l'image. Ainsi, par exemple, dans mon test j'ai téléchargé un 2688x1512 image. Dropzone a recadré et redimensionné la vignette à sa valeur par défaut 120x120, mais le fichier envoyé au serveur a été redimensionné séparément par Dropzone, à 1000x562, puis envoyé au serveur.
il y a une mise en garde intéressante ici. Les JPEGs vont être recomprimés, avec une perte, donc même une resizeQuality de 1.0 va entraîner une perte. Je vois cette fonctionnalité comme une méthode pour empêcher les fichiers démesurément grands, mais vous devriez faire attention à redimensionner deux fois si vous pouvez l'éviter (une fois sur le serveur une fois sur client.)
si ce n'est pas assez pour vous - et que vous vouliez vraiment surcharger la méthode transform - il est intéressant de noter que suivre le chemin du code à L'intérieur de Dropzone est un peu confus, parce que le createThumbnail
codepath est utilisé deux fois à chaque téléchargement, une fois pour créer une vignette comme vous vous y attendez, et encore une fois pour pré-redimensionner l'image ici avant de la Passer au serveur. De même, le resize
méthode est prêter à confusion du nom; while resizeWidth etc référez-vous à la préparation de l'image pour télécharger, taille désigne le redimensionnement de l'image, et ne fait rien à l'image envoyée au serveur.
cela peut être fait en contournant le téléchargement fait par Dropzone.js. Pour cela, vous devez définir autoQueue: false
dans les options (comme dans le Bootstrap exemple).
Ensuite, vous pouvez simplement envoyer la vignette, ou vous pouvez le faire à la dure.
Solution 1: Envoyer la vignette
myDropzone.on('thumbnail', function(file, dataURL) {
$.post('http://example.com', {img: imgToSend})
})
vous pouvez définir la façon dont vous allez redimensionner/recadrer en ajoutant la fonction redimensionner dans les options.
Solution 2: redimensionner par vous-même
il y avait un autre problème: les images peuvent avoir besoin d'être tournées (cela arrive très souvent). Pour cela, la balise d'orientation EXIF doit être utilisée. Il est apparemment perdu lorsque vous redimensionnez, donc vous devez récupérer cette information dans le frontend, avant de redimensionner. Pour cela, j'ai utilisé le Exif.bibliothèque js.
Voici un exemple de travail sur JSFiddle. Vous pouvez voir L'URI de données de l'image redimensionnée dans votre console.
Dropzone version 5 est récemment publié, donc si vous passez à dropzone 5, alors vous pouvez simplement utiliser resizeWidth et resizeHeigh pour compresser votre image du côté du client.
si vous n'en fournissez qu'un, alors dropzone respectera le format d'origine, par exemple si vous ajoutez l'option: resizeWidth: 800
alors votre image sera compressée à Largeur = 800 pixels et la ration d'aspect de votre image originale sera respectée.
Ok. Il m'a fallu un peu plus de temps pour trouver comment implémenter le redimensionnement.
Voici la solution finale qui fonctionne pour moi:
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>