Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Przesyłanie obrazów w CKEditor bez użycia wtyczki

Pisząc artykuł na swoim blogu, często będziesz musiał wyświetlać zdjęcia między tekstami, zwykle w celach ilustracyjnych. CKEditor pomaga ci to osiągnąć, ale może być trochę trudny lub trudny w obsłudze, jeśli nie używasz wtyczki. Powodem jest to, że CKEditor akceptuje tylko adres URL obrazu do wstawienia do tekstu posta, a obraz musi już istnieć w Internecie, a nie na komputerze lokalnym.

Teraz musimy znaleźć sposób na przesłanie obrazu do katalogu obrazów w naszym projekcie, gdy jeszcze piszemy post; gdy obraz zostanie przesłany, adres URL obrazu zostanie odesłany, którego możemy następnie użyć w naszym CKEditorze.

Po pierwsze dodamy przycisk, który po kliknięciu przegląda lokalny komputer użytkownika w poszukiwaniu obrazów (w taki sam sposób, w jaki zrobiłoby to kliknięcie elementu ). Gdy użytkownik wybierze obraz, ten obraz jest natychmiast przesyłany w tle za pomocą Ajax (bez ponownego ładowania strony) w zdarzeniu onChange, a adres URL tego konkretnego obrazu jest zwracany z serwera. Zwrócony adres URL jest wyświetlany w wyskakującym okienku, które jest kopiowane do schowka, gdy użytkownik go kliknie. Użytkownik może teraz kliknąć ikonę obrazu w CKEditor i wkleić do niego adres URL obrazu.

Zaimplementujmy to w miniprojekcie i zobaczmy, jak to działa.

Utwórz folder o nazwie ckeditor-images, a wewnątrz tego folderu utwórz podfolder o nazwie images i 4 pliki, a mianowicie:index.php, server.php, scripts.js i main.css.

Folder obrazów będzie zawierał obrazy przesłane z naszego CKEditora.

Otwórz index.php i umieść w nim następujący kod.

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>

Jak widać, dodaliśmy bootstrap CSS i JS przez CDN. Dodaliśmy również JQuery, ponieważ zamierzamy przesyłać obrazy za pomocą wywołań Ajax. Na koniec dodaliśmy kod wtyczki CKEditor, który musimy jeszcze zainicjować w naszym obszarze tekstowym formularza. scripts.js to miejsce, w którym będzie rezydował skrypt JQuery.

Zaraz po formularzu posta dodaliśmy kod dla wyskakującego okienka z identyfikatorem ustawionym na id="myModal". Ten mod nie jest teraz używany, ale po przesłaniu obrazu zwrócony adres URL obrazu zostanie wyświetlony w tym module. Więc na razie o tym zapomnij.

Jeśli wejdziesz na http://localhost/ckeditor-images/index.php, zobaczysz wyświetlony statyczny post i formularz. Otwórz main.css i dodajmy kilka stylów do tej strony.

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

Otwórz scripts.js i dodaj do niego ten kod:

scripts.js:

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

Odśwież stronę, a zauważysz pewne zmiany w stylizacji, a także w obszarze tekstowym, który jest teraz naszym edytorem CKEditor, załadowanym wieloma ikonami.

Utwórz bazę danych o nazwie ckeditor-images. W tej bazie danych utwórz tabelę o nazwie posty z polami:

  • id - INT(11)
  • tytuł - VARCHAR(255)
  • ciało - VARCHAR(255)

Teraz wstaw jeden lub więcej fikcyjnych postów do tabeli postów, abyśmy mogli wysłać zapytanie i wyświetlić je na stronie.

Łączenie z bazą danych

Otwórz server.php i wpisz w nim ten kod:

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

Ten kod pobiera posty z bazy danych do zmiennej $posts. Ta zmienna jest udostępniana w naszym pliku index.php przez instrukcję include w pierwszym wierszu kodu w index.php -- wiersz zawierający plik server.php wewnątrz index.php.

W pliku index.php usuń cały element div, który ma atrybut class="post" i zastąp go następującym kodem:

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

Jak widać, każdy post po kliknięciu jego tytułu prowadzi do pliku details.php przekazującego mu identyfikator posta. Utwórz plik o nazwie details.php i wklej do niego ten kod:

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>

W górnej części łączymy się z bazą danych, pobieramy identyfikator posta, który został wysłany ze strony index.php i przeszukujemy ten konkretny post. Post jest następnie przechowywany w zmiennej $post, która jest następnie wyświetlana na stronie.

Teraz możemy zacząć kodować dynamikę faktycznego przesyłania obrazu w CKEditorze. Otwórz scripts.js i zastąp wszystko w środku następującym:

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

	});
});

Postępuj zgodnie z komentarzami w tym kodzie, a zrozumiesz kroki. Najpierw użytkownik klika przycisk „prześlij obraz”. To wyzwala zdarzenie kliknięcia na wejściu pliku, którego wyświetlanie ustawiono na brak. Gdy użytkownik wybierze obraz ze swojego komputera lokalnego, na wejściu pliku zostanie wyzwolone zdarzenie onChange i to właśnie tam przesyłamy obraz za pomocą Ajax.

W tym momencie nasz obraz jest już wysyłany na serwer w żądaniu Ajax. Ale do tej pory w naszym server.php połączyliśmy się tylko z bazą danych. Nie napisaliśmy jeszcze kodu do odbierania obrazu z żądania Ajax i przesyłania go do folderu obrazów. Zróbmy to teraz.

Otwórz plik server.php jeszcze raz i dodaj do niego ten kod:

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

Ten kod akceptuje żądanie Ajax, które jest dostarczane z obrazem, przesyła obraz do folderu obrazów i zwraca w pełni kwalifikowany adres URL do obrazu. Pamiętaj, że w tym momencie użytkownik nadal jest zajęty pisaniem swojego posta w formularzu tworzenia posta, a wszystko to dzieje się w tle.

Adres URL zwrócony z serwera jest następnie wyświetlany w wyskakującym okienku, które pojawia się, aby użytkownik mógł skopiować adres URL. Gdy pojawi się modalne okno, a użytkownik kliknie wyświetlony adres URL, zostanie on skopiowany do schowka, a użytkownik może kontynuować korzystanie z tego adresu URL obrazu w CKEditor, wklejając go w odpowiednim miejscu.

Już prawie skończyliśmy z podstawową koncepcją tego samouczka. Kiedy pozostaje nam teraz nacisnąć przycisk Prześlij, aby nasz post został przesłany na serwer i zapisany w bazie danych. Aby to zrobić, dotkniemy tylko jednego pliku.

Otwórz server.php i dodaj ten kod na końcu pliku:

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

I to prowadzi nas do końca tego samouczka. Mam nadzieję, że dobrze zrozumiałeś nasz cel w tym samouczku i sposób, w jaki go rozwiązaliśmy.

 Przyjrzyj się bliżej

W tym momencie wszystko wydaje się działać dobrze. Ładujemy obraz i używamy jego adresu URL w naszym CKEditorze całkiem dobrze, ale jak wydajny jest ten system. Załóżmy, że zaczynasz pisać post, a po przesłaniu kilku zdjęć czujesz się wyczerpany, jak cofnąć przesyłanie. Jak zwolnić miejsce na serwerze? Rozwiązaniem, które proponuję, jest utworzenie tabeli obrazów w bazie danych, która przyjmuje tylko postID i nazwę obrazu. Za każdym razem, gdy przesyłasz obraz, zapisujesz nazwę obrazu w tabeli obrazów z wartością null jako postID. Jeśli zmienisz zdanie i ostatecznie nie zapiszesz posta, w tabeli obrazów pozostanie wartość null. Następnie możesz napisać skrypt, który będzie wysyłał zapytania do wszystkich obrazów bazy danych, które mają wartość null jako powiązane identyfikatory postID. Zmierz się z tym i zakoduj to. Jeśli napotkasz jakiekolwiek trudności, zostaw to w komentarzach poniżej, a pomoc nadejdzie.

Jak zawsze dziękuję za poświęcony czas. Mam nadzieję, że okaże się to pomocne. Jeśli podobał Ci się ten post, zapoznaj się z moimi innymi samouczkami oraz udostępnij i poleć moją stronę znajomym.

Pozdrawiam!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak monitorować bazy danych MySQL/MariaDB za pomocą Netdata w CentOS 7?

  2. odmowa dostępu dla użytkownika @ 'localhost' do bazy danych ''

  3. mysqli_stmt::bind_param():Liczba elementów w ciągu definicji typu nie odpowiada liczbie zmiennych wiązania

  4. Nie można było nawiązać połączenia, ponieważ maszyna docelowa aktywnie je odrzuciła (PHP / WAMP)

  5. #1055 — Wyrażenie listy SELECT nie znajduje się w klauzuli GROUP BY i zawiera kolumnę niezagregowaną, co jest niezgodne z sql_mode=only_full_group_by