Magazyn T3
newsy, felietony, testy i tutoriale



Internet Maker

07/11/2011

Przesyłanie zdjęć metodą drag&drop w HTML 5

Więcej artykułów autorstwa »
Napisane przez: Mateusz Chorążewicz
Tagi: , ,
html5-drag-drop

Dziś przedstawimy małą aplikację webową zwaną centrum przesyłania plików, która pozwoli użytkownikom wrzucać pliki z komputera za pomocą techniki drag-&-drop. Będzie to możliwe dzięki wykorzystaniu pewnych sztuczek HTML5, w których obsługę wyposażone zostały współczesne przeglądarki.

Zdjęcia będą miały podgląd i pasek postępu. Wszystko to będzie kontrolowane z poziomu klienta. Obecnie zdjęcia są przechowywane w folderze na serwerze, ale możesz to zmienić w dowolny sposób.

  

Czym jest upload plików przy użyciu HTML5?

Przesyłanie plików za pomocą HTML 5 jest w rzeczywistości połączeniem trzech technologii – File Reader API (http://www.html5rocks.com/en/tutorials/file/dndfiles/) , unowocześniona technologia drag-&-drop oraz stary dobry AJAX (z binarnym dodatkiem transferu danych). Oto opis procesu wysyłania pliku w HTML 5:

1. Użytkownik upuszcza jeden lub więcej plików z komputera wprost do okna przeglądarki. Przeglądarki, które obsługują technologię Drag & Drop uruchomią całą procedurę oraz inne użyteczne informacje, jak chociażby listę plików, które przeciągnęliśmy.
2. Korzystając z File Reader API, odczytujemy pliki na liście jako dane binarne i zapisujemy je w pamięci.
3. Używamy nowej metody sendAsBinary obiektu XMLHttpRequest i wysyłamy plik na serwer.

Brzmi to dość skomplikowanie, prawda? Na szczęście istnieją wtyczki jQuery, które mogą to wszystko zrobić za nas. Jedną z nich jest Filedrop (https://github.com/weixiyen/jquery-filedrop). Plugin ten w pełni realizuje interesujące nas zadania. Dodatkowo zawiera on również funkcje umożliwiające ograniczenie maksymalnego rozmiaru pliku oraz określenie funkcji zwrotnych. Jest to bardzo przydatne, jeśli będziemy chcieli zintegrować Filedropa z naszą aplikacją webową.

Pora więc zacząć!

HTML

Znaczniki w naszym Centrum Przesyłania Plików nie mogą być już tak naprawdę prostsze. Mamy tutaj zwykły dokument HTML 5, który zawiera odwołanie do arkusza stylów, pliku script.js, wtyczki Filedrop oraz biblioteki jQuery.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>
Upload plików w HTML5 przy pomocy technologii drag-&-drop, jQuery oraz PHP
| MagazynT3.pl Demo</title>
 
<!-- Nasz plik CSS -->
<link rel="stylesheet" href="assets/css/styles.css" />
 
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
 
<body>
 
<header>
<h1>Upload plików w HTML5</h1>
</header>
 
<div id="dropbox">
<span class="message">Upuść tutaj zdjęcie, które chcesz wrzucić.<br />
<i>(będzie ono widoczne tylko dla Ciebie)</i></span>
</div>
 
<footer>
<h2>Upload plików w HTML5 </h2>
<a class="t3" href="http://WWW.MagazynT3.pl">Czytaj & Ściągnij na WWW.MagazynT3.pl</a>
</footer>
 
<!-- Załączanie biblioteki jQuery  -->
<script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
 
<!-- Załączanie pluginu HTML5 -->
<script src="assets/js/jquery.filedrop.js"></script>
 
<!-- Główny plik skryptu -->
<script src="assets/js/script.js"></script>
 
</body>
</html>

Jedyny div, z którym Filedrop wchodzi w interakcję to #dropbox. Przekażemy ten element do pluginu, który wykryje plik, który będzie upuszczany w tym miejscu. Wiadomość umieszczona w zostanie zaktualizowana, gdy wystąpi jakiś błąd (na przykład gdy Twoja przeglądarka nie będzie wspierać jednego z elementów HTML 5, których ten przykład wymaga).

Później, gdy zdjęcie zostanie upuszczone, nasz kod jQuery wyświetli podgląd zdjęcia poprzez dodanie poniższych znaczników do strony:

<div class="preview done">
 
<span class="imageHolder">
<img src="" />
<span class="uploaded"></span>
</span>
 
<div class="progressHolder">
<div class="progress"></div>
</div>
 
</div>

Ten fragment zawiera podgląd obrazu oraz pasek postępu. Cały podgląd może mieć klasę “.done”, która powoduje wyświetlenie span “.uploaded” (domyślnie jest on ukryty). Atrybut span posiada zielony „ptaszek” w tle i oznacza, iż upload został ukończony.

Teraz przejdźmy do naszego pliku script.js

Kod jQuery

Wszystkie realne funkcjonalności transferu plików zawarte są we wtyczce Filedrop, wystarczy tylko je wywołać i przekazać kilka wywołań zwrotnych, dzięki czemu możemy ją podpiąć do naszego centrum przesyłania plików. W następnym rozdziale napiszemy mały skrypt PHP, który obsługuje przesyłanie na serwer.

Pierwszym krokiem jest napisanie funkcji pomocniczej, która pobiera dane na temat pliku i tworzy odpowiednie znaczniki dla podglądu naszego zdjęcia.

var template = '<div class="preview">'+
		'<span class="imageHolder">'+
		'<img />'+
		'<span class="uploaded"></span>'+
		'</span>'+
		'<div class="progressHolder">'+
	'<div class="progress"></div>'+
		'</div>'+
	'</div>';
 
 
	function createImage(file){
 
		var preview = $(template),
		image = $('img', preview);
 
		var reader = new FileReader();
 
		image.width = 100;
		image.height = 100;
 
		reader.onload = function(e){
 
 
		image.attr('src',e.target.result);
		};
 
 
		reader.readAsDataURL(file);
 
		message.hide();
		preview.appendTo(dropbox);
 
 
 
		$.data(file,preview);
	}

Zmienna template przechowuje kod HTML 5 dla generowania podglądu. Możemy otrzymać również DataURL naszego obrazka i dodać go jako źródło zdjęcia. Wywołajmy teraz wtyczkę filedrop:

$(function(){
 
	var dropbox = $('#dropbox'),
		message = $('.message', dropbox);
 
	dropbox.filedrop({
		//
		paramname:'pic',
 
		maxfiles: 5,
    	maxfilesize: 2,
		url: 'post_file.php',
 
		uploadFinished:function(i,file,response){
			$.data(file).addClass('done');
 
		},
 
    	error: function(err, file) {
	switch(err) {
	case 'BrowserNotSupported':
showMessage('Twoja przeglądarka nie wspiera uploadu plików HTML5!');
break;
	case 'TooManyFiles':
alert('Za dużo zdjęć! Wybierz co najwyżej 5.');
	break;
	case 'FileTooLarge':
alert(file.name+' jest za duże!. Wrzuć zdjęcie o wadze najwyżej 2 MB.');
break;
	default:
	break;
		}
		},
 
 
	beforeEach: function(file){
	if(!file.type.match(/^image\//)){
alert('Tylko zdjęcia są dozwolone!');
 
 
	return false;
		}
		},
 
uploadStarted:function(i, file, len){
	createImage(file);
		},
 
		progressUpdated: function(i, file, progress) {
		$.data(file).find('.progress').width(progress);
		}
 
	});
	var template = '…';
	function createImage(file){
// ... spójrz powyżej ...
	}
 
	function showMessage(msg){
	message.html(msg);
	}
 
});

W wyniku tego, każdy zgodny z wymaganiami obrazek jest kierowany do post_file.php, który możesz zobaczyć w następnym rozdziale.

Kod PHP

Jeśli chodzi o PHP, to nie ma żadnej różnicy pomiędzy zwykłym formularzem dla uploadu plików a techniką drag-&-drop. Oznacza to, iż można bardzo łatwo zapewnić awaryjne rozwiązanie oraz korzystać z tego samego zaplecza.

<?php
 
// Jeśli chcesz zignorować przesyłane pliki, 
// ustaw $demo_mode na true;
 
$demo_mode = false;
$upload_dir = 'uploads/';
$allowed_ext = array('jpg','jpeg','png','gif');
 
 
if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
	exit_status('Error! Wrong HTTP method!');
}
 
 
if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){
 
	$pic = $_FILES['pic'];
 
	if(!in_array(get_extension($pic['name']),$allowed_ext)){
	exit_status('Tylko '.implode(',',$allowed_ext).' pliki są dozwolone!');
	}
 
	if($demo_mode){
 
	// Przesyłanie plików jest wyłączone. Zapisujemy tylko logi.
 
$line = implode('	', array( date('r'), $_SERVER['REMOTE_ADDR'], $pic['size'], $pic['name']));
	file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND);
 
	exit_status('Upload plików jest w trybie demo.');
	}
 
 
	// Przeniesienie pliku z folderu tymczasowego
	// do folderu docelowego:
 
	if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
		exit_status('Plik wrzucony poprawnie!');
	}
 
}
 
exit_status('Coś poszło nie tak z Twoim uploadem!');
 
 
// Funkcje pomocnicze
 
function exit_status($str){
	echo json_encode(array('status'=>$str));
	exit;
}
 
function get_extension($file_name){
	$ext = explode('.', $file_name);
	$ext = array_pop($ext);
	return strtolower($ext);
}
?>

Teraz sprawmy, aby aplikacja wyglądała atrakcyjnie!

Arkusz stylów CSS

Pominąłem tę część arkusza stylów, która nie jest bezpośrednio związana z naszą aplikacją. Możesz wszystko podejrzeć w pliku styles.css.

/*-------------------------
	Element Dropbox
--------------------------*/
 
#dropbox{
	background:url('../img/background_tile_3.jpg');
 
	border-radius:3px;
	position: relative;
	margin:80px auto 90px;
	min-height: 290px;
	overflow: hidden;
	padding-bottom: 40px;
    width: 990px;
 
	box-shadow:0 0 4px rgba(0,0,0,0.3) inset,0 -3px 2px rgba(0,0,0,0.1);
}
 
#dropbox .message{
font-size: 11px;
    text-align: center;
    padding-top:160px;
    display: block;
}
 
#dropbox .message i{
	color:#ccc;
	font-size:10px;
}
 
#dropbox:before{
	border-radius:3px 3px 0 0;
}
 
/*-------------------------
	Podgląd obrazków
--------------------------*/
 
#dropbox .preview{
	width:245px;
	height: 215px;
	float:left;
	margin: 55px 0 0 60px;
	position: relative;
	text-align: center;
}
 
#dropbox .preview img{
	max-width: 240px;
	max-height:180px;
	border:3px solid #fff;
	display: block;
 
	box-shadow:0 0 2px #000;
}
 
#dropbox .imageHolder{
	display: inline-block;
	position:relative;
}
 
#dropbox .uploaded{
	position: absolute;
	top:0;
	left:0;
	height:100%;
	width:100%;
	background: url('../img/done.png') no-repeat center center rgba(255,255,255,0.5);
	display: none;
}
 
#dropbox .preview.done .uploaded{
	display: block;
}
 
/*-------------------------
	Pasek postępu
--------------------------*/
 
#dropbox .progressHolder{
	position: absolute;
	background-color:#252f38;
	height:12px;
	width:100%;
	left:0;
	bottom: 0;
 
	box-shadow:0 0 2px #000;
}
 
#dropbox .progress{
	background-color:#2586d0;
	position: absolute;
	height:100%;
	left:0;
	width:0;
 
	box-shadow: 0 0 1px rgba(255, 255, 255, 0.4) inset;
 
	-moz-transition:0.25s;
	-webkit-transition:0.25s;
	-o-transition:0.25s;
	transition:0.25s;
}
 
#dropbox .preview.done .progress{
	width:100% !important;
}

I tym sposobem nasze centrum przesyłania plików w HTML 5 jest gotowe!

Możesz go użyć jako punktu startowego do stworzenia całej usługi przesyłania, galerii HTML 5, czy też menadżera plików w Twoim panelu administratora.

Może Cię zainteresować:

  1. Wypunktować tekst w HTML-u
  2. Zmiana kodowania znaków w plikach HTML
  3. Przesyłanie plików bez publicznego IP?


O autorze

Mateusz Chorążewicz
Student Informatyki i Ekonometrii na Politechnice Gdańskiej, zapalony fotograf i multiinstrumentalista.




1 komentarz


  1. Maciej

    Można by dodać usuwanie obrazków.
    Dzięki za poradnik :)



Zostaw odpowiedź

Twój adres nie zostanie opublikowany. Wymagane pola są oznaczone *

*

Możesz używać tych tagów i atrybutów HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">