sql >> Databasteknik >  >> RDS >> Mysql

Ladda upp bilder i CKEditor utan att använda ett plugin

När du skriver en artikel på din blogg behöver du ofta visa bilder mellan texterna, vanligtvis i illustrationssyfte. CKEditor hjälper dig att uppnå detta men det kan vara lite knepigt eller svårt att arbeta med om du inte använder ett plugin. Anledningen är att CKEditor bara accepterar URL till bilden som ska infogas i inläggstexten, och bilden måste redan finnas på internet och inte på din lokala dator.

Vad vi behöver göra nu är att hitta ett sätt att ladda upp bilden till en bildkatalog i vårt projekt medan vi fortfarande skriver inlägget. när bilden har laddats upp kommer webbadressen till bilden att skickas tillbaka som vi sedan kan använda i vår CKEditor.

Det första är att vi lägger till en knapp som när du klickar på den bläddrar användarens lokala dator efter bilder (på samma sätt som ett klick på ett -element skulle göra). När användaren väl har valt en bild laddas bilden omedelbart upp i bakgrunden med Ajax (utan att ladda om sidan) i en onChange-händelse och webbadressen till den specifika bilden returneras från servern. URL-adressen som returneras visas i en popup-modal som kopieras till urklipp när användaren klickar på den. Användaren kan nu klicka på bildikonen på CKEditor och klistra in webbadressen till bilden i den.

Låt oss implementera detta i ett miniprojekt och se hur det fungerar.

Skapa en mapp som heter ckeditor-images och i denna mapp, skapa en undermapp som heter images, och 4 filer nämligen:index.php, server.php, scripts.js och main.css.

Bildmappen kommer att innehålla bilderna som laddats upp från vår CKEditor.

Öppna index.php upp och placera följande kod i den.

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>

Som du kan se har vi lagt till bootstrap CSS och JS genom CDN. Vi har också lagt till JQuery eftersom vi kommer att ladda upp bilderna med Ajax-samtal. Slutligen lade vi till CKEditor-pluginkoden som vi fortfarande ska initiera på vårt textområde i formuläret. scripts.js är där JQuery-skriptet kommer att finnas.

Strax efter inläggsformuläret lade vi till lite kod för popup-modalen med id inställt på id="myModal". Denna modal används inte nu, men när bilden har laddats upp kommer den returnerade webbadressen till bilden att visas på denna modal. Så glöm det nu.

Om du går till http://localhost/ckeditor-images/index.php kommer du att se det statiska inlägget och formuläret. Öppna main.css och låt oss lägga till några stilar på den här sidan.

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;
}

Öppna scripts.js och lägg till den här koden i den:

scripts.js:

// initialize ckeditor
CKEDITOR.replace('body');

Uppdatera sidan så kommer du att märka en förändring i stilen samt textområdet som nu är vår CKEditor laddat med många ikoner.

Skapa en databas som heter ckeditor-images. I den här databasen skapar du en tabell som heter inlägg med fält:

  • id - INT(11)
  • titel - VARCHAR(255)
  • kropp - VARCHAR(255)

Infoga nu ett eller flera dummy-inlägg i inläggstabellen så att vi kan fråga efter det och visa det på sidan.

Ansluter till databasen

Öppna server.php upp och ange denna kod i den:

<?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);
?>

Den här koden hämtar inläggen som finns i databasen till en $posts-variabel. Denna variabel görs tillgänglig i vår index.php-fil av include-satsen på den första raden i koden i index.php -- raden som inkluderar server.php-filen inuti index.php.

Ta bort hela div-elementet som har attributet class="post" i index.php-filen och ersätt det med denna kod:

// ... 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

Som du kan se leder varje inlägg när du klickar på dess titel till att details.php skickar inläggets ID till det. Skapa en fil med namnet details.php och klistra in den här koden i den:

details.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>

I den övre delen ansluter vi till databasen, tar tag i post-id:t som skickades från index.php-sidan och frågar just det inlägget. Inlägget lagras sedan i variabeln $post som sedan visas på sidan.

Nu kan vi börja koda dynamiken för att faktiskt ladda upp bilden i CKEditor. Öppna scripts.js och ersätt allt inuti med detta:

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);
				}
			});
		});

	});
});

Följ kommentarerna i den här koden så förstår du stegen. Först klickar användaren på knappen "ladda upp bild". Detta utlöser en klickhändelse på filingången vars visning har ställts in på ingen. När användaren väl väljer en bild från sin lokala dator utlöses en onChange-händelse på filinmatningen, och det är här vi laddar upp bilden med Ajax.

Vid det här laget skickas vår bild redan till servern i en Ajax-förfrågan. Men hittills i vår server.php har vi bara anslutit till databasen. Vi har ännu inte skrivit koden för att ta emot bilden från Ajax-förfrågan och ladda upp den till mappen bilder. Låt oss göra det nu.

Öppna filen server.php en gång till och lägg till denna kod till den:

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();
  	}
}

Den här koden accepterar Ajax-förfrågan som följer med bilden, laddar upp bilden till mappen bilder och returnerar en fullständigt kvalificerad URL till bilden. Kom ihåg att användaren vid det här laget fortfarande är upptagen med att skriva sitt inlägg på formuläret för att skapa inlägg och allt detta händer i bakgrunden.

Webbadressen som har returnerats från servern visas sedan i en popup-modal som dyker upp så att användaren kan kopiera webbadressen. När modalen dyker upp och användaren klickar på den visade webbadressen, kopieras den till urklippet och användaren kan fortsätta att använda denna bild-URL i CKEditor genom att klistra in denna URL på lämplig plats.

Vi är i stort sett klara med kärnkonceptet i denna handledning. När återstår nu är för oss att trycka på skicka för att vårt inlägg ska skickas till servern och sparas i databasen. För att göra det kommer vi bara att röra en fil.

Öppna server.php och lägg till denna kod i slutet av filen:

// ... 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");
}

Och det för oss till slutet av denna handledning. Jag hoppas att du väl förstod vårt mål i den här handledningen och hur vi har tagit itu med det.

 En närmare titt

Vid det här laget verkar allt fungera bra. Vi laddar upp en bild och använder dess URL i vår CKEditor helt okej, men hur effektivt är det här systemet. Låt oss säga att du börjar skriva ett inlägg och på vägen känner dig utmattad efter att ha laddat upp några bilder, hur ångrar du uppladdningarna. Hur frigör du utrymme på din server? En lösning jag skulle föreslå är att du skapar en bildtabell i databasen som endast tar postID och namnet på bilden. Varje gång du laddar upp en bild sparar du bildnamnet i bildtabellen med null som postID. Om du ändrar dig och inte sparar inlägget till slut, finns nollvärdet kvar i bildtabellen. Sedan kan du skriva ett skript som kommer att fråga alla databasbilder som har null som tillhörande postID. Utmana dig själv med detta och koda det. Om du stöter på några problem, lämna det i kommentarerna nedan så kommer hjälpen att komma.

Som alltid, tack för din tid. Hoppas du tycker att detta är till hjälp. Om du gillade det här inlägget, kolla in mina andra tutorials och dela och rekommendera min sida med dina vänner.

Med vänlig hälsning!


  1. Vad förklarar PostgreSQL exakt för mig?

  2. SQL Server Clustering från ett Oracle RAC-perspektiv

  3. PostgreSQL Skapa databas

  4. Hur man skapar ett serverlöst GraphQL API för MySQL, Postgres och Aurora