Загрузка картинок на сервер с использованием HTML5+jQuery+PHP

    Доброго времени суток!

    Наверняка многие видели в движке WP функцию переноса файлов с рабочего стола в окно браузера и их дальнейшую загрузку на сервер. Когда я увидел такое, мне стало интересно как же это организовано. Тогда я полез в дебри, чуть было не заблудился, но всё таки решение нашел. Оказывается все очень просто.

    Что нам понадобится?


    Всего лишь небольшие знания HTML5+jQuery+PHP.

    Ну что, поехали.



    Для начала распишем работу нашего мини приложения.

    1) Пользователь выбирает на своем ПК один или несколько файлов(в нашем случае графических файлов) и перетаскивает эти файлы в окно браузера который поддерживает Drag & Drop API(если точнее, то пользователь переносит файлы в специально отведенное место для загрузки).
    2) После этого у нас срабатывает событие и при помощи API мы получаем информацию о загружаемых файлах и сохраняем их во временной памяти.
    3)Далее, используя новый метод передачи sendAsBinary объекта XMLHttpRequest, посылаем наш файл из временной памяти на сервер.

    Возможно, выше описанное не совсем понятно, но сейчас все всё поймут.

    Велосипед изобретать не будем возьмем jQuery плагин FileDrop. Но так как велосипед мы не изобрели, есть один недостаток: данный плагин работает только в браузерах Firefox и Chrome. В этом нет ничего удивительного, ведь мы пишем приложение с использованием HTML5, а его поддерживают ещё не все основные браузеры. Но не будем на этом останавливаться идем далее.

    Создаем файл index.html
    С таким содержанием:
    <!DOCTYPE html>
    <html>
    	<head>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
            <title>Загрузка файлов при помощи Drag & Drop API.</title>
            <link rel="stylesheet" href="css/styles.css" />
        </head>
        <body>
            <!-- Создаем поле в которое мы будим переносить наши файлы -->
    		<div id="dropbox">
            	<!-- Напишем пояснительную записку в которой укажем что файлы необходимо кидать именно сюда -->
    			<span class="message">Перенесите сюда изображения для загрузки</span>
    		</div>
            <!-- Подключаем библиотеку jQuery -->
    		<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    		<!-- Подключаем плагин FileDrop -->
    		<script src="js/jquery.filedrop.js"></script>
    		<!-- Так же подключим еще один js скриптик которые напишем далее -->
            <script src="js/script.js"></script>
    
        </body>
    </html>
    


    Идем далее..


    Теперь создадим наш обработчик, в котором соединим действие плагина FileDrop и библиотеки jQuery, а так же создадим небольшие ограничения.
    $(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('Ваш Браузер не поддерживает HTML5!');
    					break;
    				case 'TooManyFiles':
    					alert('Разрешено загружать за 1 раз не более 5 изображений');
    					break;
    				case 'FileTooLarge':
    					alert(file.name+' Слишком большой.Разрешена загрузка файлов не более 2мб.');
    					break;
    				default:
    					break;
    			}
    		},
    
    		beforeEach: function(file){
    			if(!file.type.match(/^image\//)){
    				alert('Разрешена загрузка только изображений!!!!');
    				return false;
    			}
    		},
    		
    		uploadStarted:function(i, file, len){
    			createImage(file);
    		},
    		
    		progressUpdated: function(i, file, progress) {
    			$.data(file).find('.progress').width(progress);
    		}
        	 
    	});
    	
    	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);
    	}
    
    	function showMessage(msg){
    		message.html(msg);
    	}
    
    });
    


    Ну а теперь, сверстаем наше приложение и оформим его создав файл styles.css(находится в архиве с исходниками)

    На этом, мы заканчиваем с клиентской частью, и переходим к серверной.
    Напишем небольшой php обработчик:
    <?php
    //Создадим пару вспомагательных функций
    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);
    }
    
    $upload_dir = 'uploads/'; //Создадим папку для хранения изображений
    $allowed_ext = array('jpg','jpeg','png','gif'); //форматы для загрузки
    
    
    if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
    	exit_status('Ошибка при отправке запроса на сервер!');
    }
    
    
    if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){
    	
    	$pic = $_FILES['pic'];
    	
    	if(!in_array(get_extension($pic['name']),$allowed_ext)){
    		exit_status('Разрешена загрузка следующих форматов: '.implode(',',$allowed_ext));
    	}	
    
    //Загружаем файл на сервер в нашу папку и посылаем команду о том, что все ОК и файл загружен
    	if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
    		exit_status('Файл Был успешно загружен!');
    	}
    	
    }
    
    exit_status('Во время загрузки произошли ошибки');
    
    ?>
    

    Вот, собственно, и всё! Теперь запускаем наш локальный сервер, открываем сайт ну и тестируем. Должно получиться примерно так:
    1) Просто открытая страница браузера

    2) Загрузка 1-го файла

    3) Загрузка 2-го файла

    4) Загрузка 6-ти файлов


    На этом всё. Если мы проверим папку uploads, то в ней вы увидите все загруженные картинки.

    Исходники тут
    Демо версия тут
    Спасибо за ваше внимание!

    PS. Как цель, я не ставил перед собой задачу сделать полностью рабочее приложение для загрузки файлов на сервер и дальнейшего их просмотра. А хотел, всего лишь, продемонстрировать достаточно новый способ загрузки, который, как я думаю, многим был интересен.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 52

      –8
      Интересная статья. Спасибо.
        0
        не ИНТЕРЕСНАЯ, а ПОЛЕЗНАЯ! вроде так
        0
        Сервер принимает только один файл? Без потоков?
          0
          В данный момент на три перемещенных файла создается три потока, да. Интересно, думал ли автор о том, чтобы слать все изображения в одном запросе. Хотя бы опционально.
            +2
            Я можно сказать только начинаю осваивать HTML5 и jQuery, по этому что в моих силах реализовываю как могу. Да, хочу изучать глубже, но не всегда это получается на таком уровне как хотелось бы, всегда есть свои нюансы и такие моменты которые я не знаю как организовать. Что поделать, учусь на ошибках. Исправлюсь )
              0
              Ниже я уже кинул ссылку на свою статью, там довольно подробно описано, как слать в одном потоке.
          +5
          //strtolower($_SERVER['REQUEST_METHOD']) != 'post'
          Зачем вы приводете элемент массива $_SERVER к нижнему регистру?

          // polygon.pokodim.ru/project-1/uploads/
          Index of /project-1/uploads — закрывайте листинг дирректорий на своих серверах.

          // а хотел всего лишь продемонстрировать такой достаточно новый способ загрузки
          Единственное здесь интересное, на мой взгляд, это отлов события перемещения файла в область. С этой точки зрения тема совсем не раскрыта. Если бы вы написали как оно работает, что куда передается, как все это компенсируется в браузерах без поддержки этой функции был бы торт. А так гора верстки и стилей.
            +13
            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

            HTML5 говорите?
              –2
              Это дурная привычка, от которой не могу избавиться. Поправил.
              • НЛО прилетело и опубликовало эту надпись здесь
                • НЛО прилетело и опубликовало эту надпись здесь
                  +3
                  Непонятно, с какой целью Вы сюда выложили свой длинный CSS. Вряд ли тут оценят длину Вашего, эммм, CSS-а. Это при том, что Вы «не ставил перед собой сделать полностью рабочее приложение».
                    +24
                    Да что же творится!
                    «как использовать плагин jquery», «как удалить вредоносный base64_decode», «загадочный float:left».
                    В какой-то локальной сети закрыли форум для вебмастеров?
                      +8
                      Значит не я один заметил, что авторы топиков будто Евгения Попова перечитали. Ждем статей о использовании CSS для изменения цвета ссылок.
                        +2
                        Это похвально, что люди пишут в песочницу, но то, что такие посты проходят и правда заставляет задуматься.
                          +1
                          Это нормально, на самом деле. Ясно видно, что сейчас статьи из разряда «как пользоваться» гораздо популярнее статей «как сделать». Отсюда и результат.
                        0
                        Незаметил серверной валидации MIME-типа файла, нехорошо.
                          0
                          Не заметил*
                            +1
                            Это пример, а не режимный объект — она здесь не нужна.
                            +17
                              +4
                              Интересно: как такое попадает на главную страницу? Ведь контент не несет в себе ничего принципиально нового и универсального, а более того: попросту скопирован.

                              Я использую плагин valums.com/ajax-upload/ довольно универсальное решение, и не обязывает использовать jQuery. Правда в этом варианте бывают проблемы с mod_sequrity, который стоит отключать в .htaccess.
                              0
                              Для определения расширения, кстати, можно использовать pathinfo();
                                –1
                                Для Opera не работает. Вроде нигде не упомянули
                                  –1
                                  Но так как велосипед мы не изобрели, есть один недостаток: данный плагин работает только в браузерах Firefox и Chrome.
                                    +3
                                    А, может, хотя бы для Оперы стоило изобрести велосипед? Тем более я уже писал, как.
                                  +1
                                  Считаю загрузку файлов перетаскиванием из одного окна в другое неудобным.
                                    0
                                    считаю что удобнее метода нет
                                      +1
                                      Ну мне до сих пор диалог привычнее))
                                        0
                                        Чтобы перетащить файлы нужно открыть файловый менеджер, всё же нужно дублировать такой интерфейс обычной кнопкой, при нажатии на которую откроется диалог выбора файла.
                                        +1
                                        Учитывая то что работает всего в двух браузерах — вдвойне неудобным
                                        0
                                        Реализовал месяца 3 назад такое на чистом js без jquery, жаль opera не поддерживает пока технологий всех.
                                          0
                                          Всех не поддерживает, но в данном вопросе функционала вполне хватает(пусть и больше писать приходится).
                                            0
                                            У вас кстати тоже опера не работает, так что разница никакой в итоге.
                                              –1
                                              У меня опера работает(11.60), поэтому разница очевидна
                                                –1
                                                Может я что-то делаю не так? jpg беру с рабочего стола и переношу в область в опере 11.60 win7 x64, мне открывается это изображение, и никакая загрузка на сервер не идёт. В хроме всё окей, так что дело в опере или в вашей реализации.
                                                  0
                                                  Дело в опере, она открывает картинку просто для просмотра.
                                                    0
                                                    А значит… не работает идея ваша в ней. О чём и был весь разговор.
                                                    0
                                                    Я, наверное, вас не понимаю. Вы что имеете в виду? Моя реализация предоставляет выбор в диалоге. И о ней написано тут. И она, кстати, работает))))
                                                      +1
                                                      Извиняюсь, просто думал, что вы автор данной статьи :) А вашу (да-да, именно вашу из другой статьи :) ) я тоже видел и она работает отлично.
                                                        0
                                                        Ничего. Я, видимо, тоже некорректно ответил на ваш комментарий)
                                            0
                                            Похвально, но лучше используйте, например, plupload.com — там и хороший API, и jQuery, и graceful degradation в случае чего.
                                              0
                                              И главное, умеет загружать файл частями, что позволяет грузить произвольный размер файлов.
                                                0
                                                Это здорово, что существует хорошее профессиональное решение. Однако почему бы не написать своё, если это нравится делать.
                                                  0
                                                  Понимаете, пока новое решение проигрывает в функционале по всем статьям чему-то имеющемуся — это все игрушки, технологии потестировать, да опыт приобрести, не более.
                                                    0
                                                    Я ожидал увидеть в статье подробный разбор метода загрузки, а увидел обертку для jQuery плагина, а коли так — лучше бы брали Plupload, и уже для него писали обертку, т.к. он банально мощнее.
                                                0
                                                На хабре уже имеется статья, по сравнению с которой, текущая выглядит уныло.
                                                HTML5 File API: множественная загрузка файлов на сервер
                                                  +4
                                                  <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
                                                  

                                                  charset какой забавный… А почему не UTF-8?
                                                    –3
                                                    Потому что земля круглая и она вращается
                                                    0
                                                    Вещь полезная, жаль правда не для всех осликов.
                                                      0
                                                      Эмм… у меня возник только один вопрос… а как картинки удалять, если случайно не тут кинул? Не заново же перезагружать страницу…
                                                        0
                                                        если так углубляться, то и вывода загруженных картинок нет и т.д., это уже параллельная тема работа с файлами называется, в статье я указывал только загрузку файлов на сервер при помощи переноса файлов в окно браузера
                                                        0
                                                        Буду благодарен если кто то поделится красивым решением для привязки кнопки выбора нескольких файлов (и загрузке через данный скрипт filedrop.js) для версии на iOS. Желательно сразу на jsfiddle или подобном сервисе. Тапом по полю дропа или кнопки загрузить файлы.

                                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                        Самое читаемое