Post Top Ad

Your Ad Spot

jueves, 7 de mayo de 2020

Carga de imágenes en CKEditor sin usar un complemento

Al escribir un artículo en su blog, a menudo necesitará mostrar imágenes entre textos, generalmente con fines ilustrativos. CKEditor lo ayuda a lograr esto, pero puede ser un poco complicado o difícil trabajar si no está utilizando un complemento. La razón es que CKEditor solo acepta la URL de la imagen que se insertará en el texto de la publicación, y la imagen ya debe existir en Internet y no en su máquina local.
Lo que tenemos que hacer ahora es encontrar una manera de subir la imagen a un  directorio de imágenes en nuestro proyecto mientras todavía estamos escribiendo la publicación; una vez que la imagen ha sido cargada, la URL de la imagen se enviará de vuelta, que luego podemos usar en nuestro CKEditor.
Lo primero es que agregaremos un botón que, cuando se hace clic, navega por la computadora local del usuario en busca de imágenes (de la misma manera que haría clic en un elemento <input type = "file" />). Una vez que el usuario selecciona una imagen, esa imagen se carga inmediatamente en segundo plano usando Ajax (sin volver a cargar la página) en un evento onChange y la URL de esa imagen en particular se devuelve desde el servidor. La URL devuelta se muestra en un modo emergente que se copia al portapapeles cuando el usuario hace clic en él. El usuario ahora puede hacer clic en el icono de la imagen en el CKEditor y pegar la URL de la imagen en él.
Implementemos esto en un mini proyecto y veamos cómo funciona.
Cree una carpeta llamada ckeditor -images y dentro de esta carpeta, cree una subcarpeta llamada images y 4 archivos, a saber: index. php , server.php , scripts.js y main.css .
La carpeta de imágenes contendrá las imágenes cargadas desde nuestro CKEditor. 
Abra index.php y coloque el siguiente código en él.
index.php:
<?php include('server.php') ?>

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Uploading images in CKEditor using PHP</title>
	<!-- Bootstra CSS -->
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />

	<!-- Custom styling -->
	<link rel="stylesheet" href="main.css">
</head>
<body>
	
<div class="container">
	<div class="row">
		<div class="col-md-8 col-md-offset-2 post-div">

			<!-- Display a list of posts from database -->
			<?php foreach ($posts as $post): ?>
				<div class="post">
					<h3>
						<a href="details.php?id=<?php echo $post['id'] ?>"><?php echo $post['title']; ?></a>
					</h3>
					<p>
						<?php echo html_entity_decode(preg_replace('/\s+?(\S+)?$/', '', substr($post["body"], 0, 200))); ?>
						
					</p>
				</div>				
			<?php endforeach ?>

			<!-- Form to create posts -->
			<form action="index.php" method="post" enctype="multipart/form-data" class="post-form">
				<h1 class="text-center">Add Blog Post</h1>
				<div class="form-group">
					<label for="title">Title</label>
					<input type="text" name="title" class="form-control" >
				</div>

				<div class="form-group" style="position: relative;">
					<label for="post">Body</label>
					
					<!-- Upload image button -->
					<a href="#" class="btn btn-xs btn-default pull-right upload-img-btn" data-toggle="modal" data-target="#myModal">upload image</a>

					<!-- Input to browse your machine and select image to upload -->
					<input type="file" id="image-input" style="display: none;">

					<textarea name="body" id="body" class="form-control" cols="30" rows="5"></textarea>

					</div>
					<div class="form-group">
						<button type="submit" name="save-post" class="btn btn-success pull-right">Save Post</button>
					</div>
			</form>

			<!-- Pop-up Modal to display image URL -->
			<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
			  <div class="modal-dialog" role="document">
			    <div class="modal-content">
			      <div class="modal-header">
			        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
			        <h4 class="modal-title" id="myModalLabel">Click below to copy image url</h4>
			      </div>
			      <div class="modal-body">
					<!-- returned image url will be displayed here -->
					<input 
						type="text" 
						id="post_image_url" 
						onclick="return copyUrl()" 
						class="form-control"
						>
					<p id="feedback_msg" style="color: green; display: none;"><b>Image url copied to clipboard</b></p>
			      </div>
			    </div>
			  </div>
			</div>
		</div>

	</div>
</div>

<!-- JQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- CKEditor -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.8.0/ckeditor.js"></script>

<!-- custom scripts -->
<script src="scripts.js"></script>

</body>
</html>
Como puede ver, hemos agregado Bootstrap CSS y JS a través de CDN. También agregamos JQuery porque vamos a subir las imágenes usando llamadas Ajax. Por último, agregamos el código del complemento CKEditor que todavía debemos inicializar en nuestro área de texto en el formulario. scripts.js es donde residirá el script JQuery.
Justo después del formulario de publicación, agregamos un código para el modal emergente con id establecido en id = "myModal". Este modal no se está utilizando ahora, pero cuando la imagen se ha cargado, la URL devuelta de la imagen se mostrará en este modal. Así que olvídalo por ahora.
Si va a http: //localhost/ckeditor-images/index.php, verá la publicación estática que se muestra y el formulario. Abra main.css y agreguemos algunos estilos a esta página.http : // localhost ckeditor images index php , verá la publicación estática que se muestra y el formulario. Abra main.css y agreguemos algunos estilos a esta página.
main.css:
p {
	font-size: 1.1em;
}
.post {
	border: 1px solid #ccc;
	padding: 10px;
	margin-top: 15px;
}
.post h3 {
	margin: 0px;
}
.post-div {
	border: 1px solid #ccc;
	margin-top: 30px;
	margin-bottom: 30px;
	padding: 20px;
}
.post-form {
	margin-top: 80px;
}
/*DETAILS PAGE*/
.post-details p {
	text-align: justify;
	margin: 20px auto;
	font-size: 1.2em;
}
.upload-img-btn {
	position: absolute; 
	z-index: 9; 
	top: 35px;
	right: 5px;
}
Abra scripts.js y agregue este código dentro de él:
scripts.js:
// initialize ckeditor
CKEDITOR.replace('body');
Actualice la página y notará algunos cambios en el estilo, así como en el área de texto que ahora es nuestro CKEditor cargado con muchos íconos.
Cree una base de datos llamada ckeditor-images.  En esta base de datos, cree una tabla llamada posts con campos:
  • id - INT (11)
  • título - VARCHAR (255)
  • cuerpo - VARCHAR (255)
Ahora inserte una o más publicaciones ficticias en la tabla de publicaciones para que podamos consultarla y mostrarla en la página. 

Conectando a la base de datos

Abra server.php e ingrese este código en él:
<?php 
	// connect to database
	$db = mysqli_connect("localhost", "root", "", "ckeditor-images");

	// retrieve posts from database
	$result = mysqli_query($db, "SELECT * FROM posts");
	$posts = mysqli_fetch_all($result, MYSQLI_ASSOC);
?>
Este código recupera las publicaciones que están en la base de datos en una  variable $ posts . Esta variable está disponible en nuestro archivo index.php mediante la instrucción include en la primera línea de código en index.php, la línea que incluye el archivo server.php dentro de index.php . 
En el archivo index.php, elimine todo el elemento div que tenga el atributo  class = "post" y reemplácelo con este código:
// ... more code here

<?php if (isset($posts)): ?>
	<?php foreach ($posts as $post): ?>
		<div class="post">
			<h3>
				<a href="details.php?id=<?php echo $post['id'] ?>"><?php echo $post['title'] ?></a>
			</h3>
			<p><?php echo $post['body']; ?></p>
		</div>
	<?php endforeach ?>
<?php else: ?>
	<h2>No posts available</h2>
<?php endif ?>

// ... more code here
Como puede ver, cada publicación al hacer clic en su título, lleva a los detalles.php que le  pasa la identificación de la publicación. Cree un archivo llamado details.php y pegue este código en él:
detalles.php:
<?php 
	// connect to database
    $db = mysqli_connect("localhost", "root", "", "ckeditor-images");

	if (isset($_GET['id'])) {
		$id = $_GET['id'];
		$result = mysqli_query($db, "SELECT * FROM posts WHERE id=$id");

		$post = mysqli_fetch_assoc($result);
	}
?>
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Uploading images in CKEditor using PHP</title>

	<!-- Bootstra -->
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />

	<!-- Custom styling -->
	<link rel="stylesheet" href="main.css">

</head>
<body>
	
	<div class="container">
		<div class="row">
			<div class="col-md-8 col-md-offset-2 post-div">
				<div class="post-details">
					<h2><?php echo $post['title'] ?></h2>
					<p><?php echo html_entity_decode($post['body']); ?></p>
				</div>				
			</div>
		</div>
	</div>

<!-- JQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>

<!-- JQuery scripts -->
<script>

</script>

</body>
</html>
En la sección superior, nos conectamos a la base de datos, tomamos la identificación de la publicación que se envió desde la página index.php y consultamos esa publicación en particular. La publicación se almacena en la variable $ post que luego se muestra en la página.
Ahora podemos comenzar a codificar la dinámica de cargar realmente la imagen en el CKEditor. Abra scripts.js y reemplace todo lo que está adentro con esto:
scripts.js:
// initialize ckeditor
CKEDITOR.replace('body');

// Javascript function to copy image url to clipboard from modal
function copyUrl() {
  var copyText = document.getElementById("post_image_url");
  copyText.select();
  document.execCommand("Copy");

  // replace url with confirm message 
  $('#post_image_url').hide(1000);
  $('#feedback_msg').show();

  // hide modal after 2 seconds
  setTimeout(function(){
	  $('#myModal').modal('hide');
	  $('#feedback_msg').hide();
	  $('#post_image_url').show();
  }, 2000);
}

$(document).ready(function(){
	// When user clicks the 'upload image' button
	$('.upload-img-btn').on('click', function(){
		
		// Add click event on the image upload input
		// field when button is clicked
		$('#image-input').click();


		$(document).on('change', '#image-input', function(e){

			// Get the selected image and all its properties
			var image_file = document.getElementById('image-input').files[0];

			// Initialize the image name
			var image_name = image_file.name;

			
			// determine the image extension and validate image
			var image_extension = image_name.split('.').pop().toLowerCase();
			if (jQuery.inArray(image_extension, ['gif', 'png', 'jpg', 'jpeg']) == -1) {
				alert('That image type is not supported');
				return;
			} 

			// Get the image size. Validate size
			var image_size = image_file.size;
			if (image_size > 3000000) {
				alert('The image size is too big');
				return;
			} 


			// Compile form values from the form to send to the server
			// In this case, we are taking the image file which 
			// has key 'post_image' and value 'image_file'
			var form_data = new FormData();
			form_data.append('post_image', image_file);
			form_data.append('uploading_file', 1);

			// upload image to the server in an ajax call (without reloading the page)
			$.ajax({
				url: 'index.php',
				method: 'POST',
				data: form_data,
				contentType: false,
				cache: false,
				processData: false,
				beforeSend : function(){

				},
				success : function(data){
					// how the pop up modal
					$('#myModal').modal('show');

					// the server returns a URL of the uploaded image
					// show the URL on the popup modal
					$('#post_image_url').val(data);
				}
			});
		});

	});
});
Siga los comentarios en este código y comprenderá los pasos. Primero, el usuario hace clic en el botón "cargar imagen". Esto desencadena un evento de clic en la entrada del archivo cuya visualización se ha establecido en ninguno. Una vez que el usuario selecciona una imagen de su computadora local, se activa un evento onChange en la entrada del archivo, y aquí es donde cargamos la imagen usando Ajax.
En este punto, nuestra imagen ya se está enviando al servidor en una solicitud de Ajax. Pero hasta ahora en nuestro server.php, solo nos hemos conectado a la base de datos. Todavía no hemos escrito el código para recibir la imagen de la solicitud de Ajax y subirla a la carpeta de imágenes . Hagámoslo ahora.
Abra el archivo server.php una vez más y agregue este código:
server.php:
// ... more code here ...

// if 'upload image' buttton is clicked
if (isset($_POST['uploading_file'])) {
	// Get image name
  	$image = $_FILES['post_image']['name'];

  	// image file directory
  	$target = "images/" . basename($image);

  	if (move_uploaded_file($_FILES['post_image']['tmp_name'], $target)) {
  		echo "http://localhost/ckeditor-images/" . $target;
  		exit();
  	}else{
  		echo "Failed to upload image";
  		exit();
  	}
}
Este código acepta la solicitud de Ajax que viene con la imagen, carga la imagen en la carpeta de imágenes y devuelve una URL totalmente calificada a la imagen. Recuerde que en este momento el usuario todavía está ocupado escribiendo su publicación en el formulario de creación de publicaciones y todo esto está sucediendo en segundo plano.
La URL que ha sido devuelta desde el servidor se muestra en un modo emergente que aparece para que el usuario copie la URL. Cuando aparece el modal y el usuario hace clic en la URL que se muestra, se copia en el portapapeles y el usuario puede proceder a usar esta URL de imagen en CKEditor pegando esta URL en el lugar apropiado.
Ya hemos terminado con el concepto central de este tutorial. Cuando queda ahora es para nosotros presionar enviar para que nuestra publicación se envíe al servidor y se guarde en la base de datos. Para hacer eso, solo tocaremos un archivo. 
Abra server.php y agregue este código al final del archivo:
// ... more code here ...

// if form save button is clicked, save post in the database
if (isset($_POST['save-post'])) {
	$title = mysqli_real_escape_string($db, $_POST['title']);
	$body = htmlentities(mysqli_real_escape_string($db, $_POST['body']));

	$sql = "INSERT INTO posts (title, body) VALUES ('$title', '$body')";
	mysqli_query($db, $sql);
	header("location: index.php");
}
Y eso nos lleva al final de este tutorial. Espero que haya entendido bien nuestro objetivo en este tutorial y cómo lo hemos abordado.

 Una mirada más cercana

En este punto, todo parece estar funcionando bien. Estamos cargando una imagen y usando su URL en nuestro CKEditor, está bien, pero qué tan eficiente es este sistema. Digamos que comienzas a escribir una publicación y en el camino te sientes agotado después de haber subido algunas imágenes, ¿cómo deshaces las cargas? ¿Cómo liberas espacio en tu servidor? Una solución que propondría es que cree una tabla de imágenes en la base de datos que tome solo el postID y el nombre de la imagen. Cada vez que carga una imagen, guarda el nombre de la imagen en la tabla de imágenes con nulo como postID. Si cambia de opinión y no guarda la publicación al final, el valor nulo permanece en la tabla de imágenes. Luego, puede escribir un script que consultará todas las imágenes de la base de datos que tengan nulos como sus postID asociados. Ponte a prueba con esto y codifícalo. Si encuentra alguna dificultad,
Como siempre, gracias por tu tiempo. Espero que encuentres esto útil. Si te gustó esta publicación, consulta mis otros tutoriales y comparte y recomienda mi sitio con tus amigos. 

No hay comentarios.:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

outbrain

Páginas