Ce problème vient du fait que lors du téléchargement de fichiers image, l'arrière-plan limite la taille à 2 Mo, mais lorsque l'appareil photo est allumé pour prendre des photos, elle dépasse 2 Mo chaque minute afin de ne pas affecter l'expérience utilisateur et les exigences fonctionnelles. le front-end doit compresser la taille, puis la télécharger dans les coulisses.
Analyse des idéesAprès avoir recherché de nombreuses informations, j'ai découvert que seul Canvas peut compresser des images.
Le principe est à peu près le suivant : 1. Convertissez d'abord le fichier fichier de l'image en baseURL 2. Créez une balise d'image pour recevoir le fichier et obtenir la largeur, la hauteur et les proportions de l'image. 3. Créez un canevas et définissez la taille du canevas. 4. Dessinez l'image sur la toile. 5. Compressez le canevas et obtenez une nouvelle baseURL. 6. Reconvertissez la baseURL en fichier.
fonction du local Convertir le fichier en base64/*** @param {flux de fichiers binaires} fichier * @param {fonction de rappel, return base64} fn */function changeFileToBaseURL(file,fn){ // Crée un objet fichier lu var fileReader = new FileReader( //); Si le fichier n'est pas défini, renvoie null if(file == undefined) return fn(null); // Lit le fichier file, le résultat est fileReader.readAsDataURL(file); fileReader.onload = function(){ // Lire la variable base64 imgBase64Data = this.result;Convertir base64 en flux de fichiers
/** * Convertir base64 en fichier * @param {baseURL} dataurl * @param {file name} filename * @return {file binaire stream}*/function dataURLtoFile(dataurl, filename) { var arr = dataurl.split(' , '), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); return new File([u8arr], filename, {type:mime});Méthode de compression
/*** image compressée du canevas* @param {paramètre obj} param * @param {flux binaire du fichier} param.file requis* @param {taille de compression cible} param.targetSize ne réussit pas l'affectation initiale -1* @param {output Largeur de l'image} param.width ne transmet pas la valeur d'affectation initiale -1 et ne transmet pas la hauteur pour la mise à l'échelle proportionnelle* @param {nom de l'image de sortie} param.fileName ne transmet pas l'image d'affectation initiale* @param {degré de l'image compressée } param.quality ne transmet pas la valeur d'affectation initiale de 0,92. Plage de valeurs 0~1* @param {fonction de rappel} param.succ requis */function pressImg(param){ //S'il n'y a pas de fonction de rappel, elle ne sera pas exécutée if(param && param.succ){ //Si le fichier n'est pas défini, return null if(param.file == undefined) return param.succ(null); //Attacher une valeur initiale au paramètre param.targetSize = param.hasOwnProperty(targetSize)? param.targetSize : -1; param.width = param.hasOwnProperty(width) ? param.width : -1; param.fileName = param.hasOwnProperty(fileName) ? qualité) ? param.quality : 0.92; var _this = this; // Récupère le type de fichier var fileType = param.file.type; // console.log(fileType) //image/jpeg if(fileType.indexOf(image) == -1){ console.log('Veuillez sélectionner un fichier image^_^'); return param.succ(null); } //Si la taille actuelle est inférieure à la taille cible, affichez directement var size = param.file.size; if(param.targetSize > size){ return param.succ(param.file); ); } // Lisez le fichier fichier et le résultat est base64 changeFileToBaseURL(param.file,function(base64){ if(base64){ var image = new Image(); image.src = base64; image.onload = function(){ / / Get le rapport hauteur/largeur var scale = this.width / this.height; // console.log(scale); //Créer un canevas var canvas = document.createElement('canvas'); //Obtenir le contexte var context = canvas.getContext('2d'); //Obtenir la largeur de l'image compressée Si la largeur est -1, la largeur par défaut de l'image originale canvas.width = param.width == -1? width : param.width; //Obtenir la hauteur de l'image compressée Si la largeur est -1, la hauteur de l'image originale par défaut est canvas.height = param.width == -1? parseInt(param.width / scale); //Dessinez l'image sur le canevas context.drawImage(image, 0, 0, canvas.width, canvas.height); //Compressez l'image et obtenez une nouvelle base64Url var newImageData = canvas .toDataURL(fileType,param.quality); //Convertir base64 en flux de fichiers var resultFile = dataURLtoFile(newImageData,param.fileName); //Juge si targetSize est limité et que la taille de l'image compressée est supérieure à la taille cible, une erreur apparaîtra if(param.targetSize != -1 && param.targetSize < resultFile.size ){ console .log(La taille de téléchargement de l'image est trop grande, veuillez la télécharger à nouveau^_^ param.succ(null); // Renvoie le flux de fichiers param.succ(resultFile); } } } } } ;Utilisation de la méthode
La taille du fichier est en octets, nous devons donc convertir la taille requise en octets. 1 octet équivaut à 1 octet équivaut à 1B, 1 Ko = 1024B, 1 Mo = 1024 * 1024B
<input type=file id=fileImg class=fileImg/>
//Obtenir l'url de téléchargement du fichier image$(#fileImg).on('change',function(){ pressImg({ file:this.files[0], targetSize:2 * 1024 * 1024, qualité:0.5, largeur:600 , succ:function(resultFile){ //S'il n'est pas nul, la compression est réussie if(resultFile){ //TODO } } })});Résumé du problème Niveau de compression des images
Le degré de compression de l'image n'est pas facile à déterminer, vous pouvez donc l'essayer plusieurs fois et l'ajuster en fonction des exigences du demandeur. La modification de la taille et de la résolution de l'image cible peut modifier le degré de compression de l'image.
À l'origine, je voulais effectuer un processus récursif de compression d'images jusqu'à ce que la taille de l'image réponde aux attentes.Plus tard découvert
Parce que lorsque iOS appelle la caméra système pour prendre des photos, elle pivote de 90 degrés dans le sens inverse des aiguilles d'une montre. Après avoir compressé l'image et l'avoir envoyée en arrière-plan, j'ai constaté que la direction de prise de vue des informations exif de l'image était perdue, provoquant une rotation des images téléchargées par iOS de 90 degrés dans le sens inverse des aiguilles d'une montre. Android n'a jamais remarqué ce problème.
À l'heure actuelle, on soupçonne qu'il a été perdu lorsque la base64 a été convertie en fichier fichier. Des instructions supplémentaires seront fournies ici après vérification.
@version1.0-2019-8-2-Create "Utiliser le canevas pour compresser la taille de l'image"
©burning_Yun Qiqi
Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.