Esse problema decorre do fato de que ao enviar arquivos de imagem o fundo limita o tamanho a 2 MB, mas quando a câmera é ligada para tirar fotos ultrapassa 2 MB a cada minuto para não afetar a experiência do usuário e os requisitos funcionais. o front-end precisa compactar o tamanho e depois carregá-lo.
Análise de ideiasDepois de pesquisar muitas informações, descobri que apenas o canvas pode compactar imagens.
O princípio é aproximadamente o seguinte: 1. Primeiro converta o arquivo da imagem em baseURL 2. Crie uma tag de imagem para receber o arquivo e obter a largura, altura e proporção da imagem. 3. Crie uma tela e defina o tamanho da tela. 4. Desenhe a imagem na tela. 5. Compacte a tela e obtenha um novo baseURL. 6. Converta o baseURL novamente em um arquivo.
função de premissa Converter arquivo de arquivo para base64/*** @param {fluxo de arquivo binário} file * @param {função de retorno de chamada, return base64} fn */function changeFileToBaseURL(file,fn){ // Cria um objeto de arquivo de leitura var fileReader = new FileReader(); Se o arquivo não estiver definido, retorne null if(file == undefined) return fn(null); // Leia o arquivo file, o resultado é base64-bit fileReader.readAsDataURL(file); fileReader.onload = function(){ // Leia o base64 var imgBase64Data = this.result;Converter base64 em fluxo de arquivo
/** * Converte base64 em arquivo * @param {baseURL} dataurl * @param {nome do arquivo} nome do arquivo * @return {fluxo binário do arquivo}*/function dataURLtoFile(dataurl, nome do arquivo) { 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], nome do arquivo, {type:mime} });Método de compressão
/*** imagem compactada da tela* @param {parâmetro obj} param * @param {fluxo binário do arquivo} param.file obrigatório* @param {tamanho de compactação do destino} param.targetSize não passa na atribuição inicial -1* @param {saída Largura da imagem} param.width não passa o valor de atribuição inicial -1 e não passa a altura para escala proporcional* @param {nome da imagem de saída} param.fileName não passa a imagem de atribuição inicial* @param {grau da imagem compactada } param.quality não passa no valor de atribuição inicial de 0,92. Intervalo de valores 0~1* @param {função de retorno de chamada} param.succ necessário */function pressImg(param){ //Se não houver função de retorno de chamada, ela não será executada if(param && param.succ){ //Se arquivo não está definido, retorne nulo if(param.file == indefinido) return param.succ(null); //Anexar um valor inicial ao parâmetro param.targetSize = param.hasOwnProperty(targetSize)? param.targetSize: -1; param.width = param.hasOwnProperty(largura) ? param.width: -1; qualidade) ? param.quality : 0.92; var _this = this; = param.file.type; // console.log(fileType) //image/jpeg if(fileType.indexOf(image) == -1){ console.log('Selecione um arquivo de imagem^_^'); return param.succ(null } //Se o tamanho atual for menor que o tamanho alvo, produza diretamente var size = param.file.size; if(param.targetSize > size){ return param.succ(param.file; ); Leia o arquivo file e o resultado é base64 changeFileToBaseURL(param.file,function(base64){ if(base64){ var image = new Image(); image.src = base64; image.onload = function(){ / / Get a proporção var scale = this.width / this.height; // console.log(scale); //Criar uma tela var canvas = document.createElement('canvas'); //Obter o contexto var context = canvas.getContext('2d'); //Obter a largura da imagem compactada. Se a largura for -1, a largura padrão da imagem original canvas.width = param.width == -1? width : param.width; //Obter a altura da imagem compactada. Se a largura for -1, a altura da imagem original padrão é canvas.height = param.width == -1? parseInt(param.width / scale); //Desenha a imagem na tela context.drawImage(image, 0, 0, canvas.width, canvas.height); //Compacta a imagem e obtém um novo base64Url var newImageData = canvas); .toDataURL(fileType,param.quality); //Converter base64 em um fluxo de arquivo var resultFile = dataURLtoFile(newImageData,param.fileName); //Julgar se targetSize for limitado e o tamanho da imagem compactada for maior que o tamanho de destino, um erro aparecerá if(param.targetSize != -1 && param.targetSize < resultFile.size); ){ console .log(O tamanho do upload da imagem é muito grande, faça upload novamente^_^); //Retorna o fluxo do arquivo param.succ(resultFile);Uso do método
O tamanho do arquivo está em bytes, então precisamos converter o tamanho necessário em bytes. 1 byte é 1 byte é 1B, 1KB = 1024B, 1MB = 1024 * 1024B
<tipo de entrada=arquivo id=fileImg class=fileImg/>
//Obter URL de upload do arquivo de imagem$(#fileImg).on('change',function(){ pressImg({ file:this.files[0], targetSize:2 * 1024 * 1024, qualidade:0,5, largura:600 , succ:function(resultFile){ //Se não for nulo, a compactação foi bem-sucedida if(resultFile){ //TODO } } })});Resumo do problema Nível de compactação de imagem
O grau de compressão da imagem não é fácil de determinar, então você pode tentar várias vezes e ajustá-lo de acordo com as necessidades do solicitante. Alterar o tamanho e a resolução da imagem alvo pode alterar o grau de compactação da imagem.
Originalmente eu queria fazer um processo recursivo de compactação de imagens até que o tamanho da imagem atendesse às expectativas.Mais tarde descobri
Porque quando o iOS acessa a câmera do sistema para tirar fotos, ela gira 90 graus no sentido anti-horário. Depois de compactar a imagem e enviá-la para o fundo, descobri que a direção de disparo das informações exif da imagem foi perdida, fazendo com que as imagens carregadas pelo iOS girassem 90 graus no sentido anti-horário. O Android nunca percebeu esse problema.
Atualmente, há algumas suspeitas de que ele foi perdido quando o base64 foi convertido em um arquivo. Instruções adicionais serão fornecidas aqui após a verificação.
@version1.0-2019-8-2-Create "Use canvas para compactar o tamanho da imagem"
©burning_Yun Qiqi
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.