Recortando e fazendo upload de imagens com preview usando o Croppie.js + PHP

PHP Logo
PHP Logo

Sobre o Croppie: É uma biblioteca que se propõe a ser leve, rápida e simples nas funções de recortar e fazer pequenas alterações nas imagens no client-side.

Com base nos exemplos da documentação do Croppie, eu fiz um exemplo mostrando como usar um pouco do croppie.js para fazer upload de imagens recortadas para o server-side, usando PHP, e por meio do método .ajax() do jQuery para fazer requisições assíncronas.

index.php

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Crop and upload</title>
    <link rel="stylesheet" href="node_modules/croppie/croppie.css">
    <link rel="stylesheet" href="exemplo.css">
	<script src="node_modules/jquery/dist/jquery.min.js" type="text/javascript"></script>
	<script src="node_modules/croppie/croppie.js" type="text/javascript"></script>
    <script src="node_modules/exif-js/exif.js" type="text/javascript"></script>
	<script src="exemplo.js" type="text/javascript"></script>
</head>
<body>

    <div id="response"></div>

    <div class="demo-wrap upload-demo">
        <div class="upload-demo-wrap">
            <div class="croppie-container" id="upload-demo"></div>
        </div>
    </div>

    <form method="post" id="img-upload" enctype="multipart/form-data">
        <label>Nome da imagem:(opcional)</label>
        <input type="text" name="name-img" class="form-vertical">
        <label>Imagem para recortar:</label>
        <input type="file" accept="image/*" id="img" class="form-vertical">
        <input type="submit" class="form-vertical">
    </form>
    <img id="img-preview" src="" alt="preview"> 

</body>

Para usar o Croppie basta adicionar os arquivos croppie.js e o croppie.css, mas nesse exemplo é requerido o jQuery e o exif.js.

exemplo.js

$(document).ready(function(){

	function CropUpload() {

		var $uploadCrop;
		var blob;

		function readFile(input) {
			if (input.files && input.files[0]) {
							var reader = new FileReader();
							reader.onload = function (e) {
					$('.upload-demo').addClass('ready');
								$uploadCrop.croppie('bind', {
									url: e.target.result
								}).then(function(){
									console.log('Imagem lida com sucesso');
								});
							}
							reader.readAsDataURL(input.files[0]);
					}
					else {
						swal("Seu navegador não suporta o FileReader API");
				}
		}

		$uploadCrop = $('#upload-demo').croppie({
			viewport: {
				width: 450,
				height: 400,
				type: 'square'
			},
			boundary: {
					width: 550,
					height: 400
			},
			update: function(resp){
					$uploadCrop.croppie('result', {
						type: 'canvas'
					}).then(function (resp) {
						$('#img-preview').attr('src', resp);
					});
					$uploadCrop.croppie('result', {
						type: 'blob'
					}).then(function (resp) {
						blob = resp;
					});
			},
                        enableExif: true
		});

		$('#img').on('change', function () {
			readFile(this);
		});
	
		$('form#img-upload').submit(function (ev) {
			ev.preventDefault();

			var data = new FormData(this);
			
			data.append('img-h', blob);

				$.ajax({
					type: "POST",
					enctype: 'multipart/form-data',
					url: "upload.php",
					data: data,
					processData: false,
					contentType: false,
					success: function (data) {
						$("#response").html(data);
						console.log(data);
					},
					error: function (ev) {
						$("#response").text(ev.responseText);
						console.log(ev);
					}
				});
		});
	}

	CropUpload();

});

exemplo.js: é onde a mágica acontece, nele configuramos os eventos e em como a imagem será cortada e enviada, boundary especifica o tamanho fora da área de corte ou um tamanho geral da div que vai conter a imagem a ser cortada, viewport especifica uma área de corte e seu formato que podem ser do tipo: square ou circle , você pode ver mais sobre as configurações na documentação do croppie.

Quando ocorre um submit do formulário fazemos um .append() do blob do recorte atual da imagem aos dados do formulário, em outras palavras: adicionamos o recorte atual aos dados do formulário do usuário e enviamos ao servidor de forma assíncrona na chave “img-h”.[1]

Outro ponto importante é o preview, basicamente é feito por meio de mudar o value do src com a Base64 do recorte da imagem.

upload.php

<?php 
echo $_POST['name-img'] . '<br><br>';
if(isset($_FILES['img-h'])){
    $dir = 'uploads/';
    $file_path = $dir . uniqid() . '.png';
    if(move_uploaded_file($_FILES['img-h']['tmp_name'], $file_path)){
        echo "Sucesso: imagem cortada e salva com sucesso";
    }
    else{
        echo "Erro: imagem cortada e não salva";
    }
}
?>

upload.php: retorna para o jQuery o input text e verifica se a array $_FILES de chave ‘img-h’ contém algo, se contiver tentará fazer upload da imagem com nome gerado pela função uniqid()[2].

Notas:
1. Pode-se enviar a imagem para o servidor por meio de uma base64 da imagem recortada mas eu acho que isso toma mais processamento do servidor porque você tem que decodificar e escrever o arquivo de imagem.
2. Cuidado, esse código é apenas para fins didáticos deve-se fazer várias checagens para fazer um sistema de upload seguro de imagens, uniqid() por exemplo não é uma função muito recomendada para id únicos.

Deixe uma resposta

O seu endereço de e-mail não será publicado.