Загрузка изображения на сервер с предварительным просмотром при помощи HTML5 Drag and Drop

Здравствуйте, уважаемые читатели XoZbloga! За последнее время я получил несколько предложений сделать урок, на тему загрузки изображений на сервер с предварительным просмотром. В этом уроке я попытаюсь разобрать данную тему, чтобы у Вас не осталось вопросов. Загрузка будет осуществляться с помощью HTML5 Drag and Drop (перетащил и бросил).

HTML5 Drag and Drop загрузчик изображений

Для создания данного загрузчика будем использовать следующие:

  • HTML5 File API (FileReader);
  • Drag and Drop API;
  • PHP сценарий для загрузки на сервер.

Сразу напомню, что исходники работают только на сервере.

HTML разметка

Страница состоит из области для перетаскивания, а также области предварительного просмотра. Идея заключается в том, чтобы захватить изображения на рабочем столе (или в папке) и перетащить в область указанную пунктиром на странице, или если удобно нажать на кнопку «Выбрать файлы» по «старинке». После чего выбранные картинки отобразятся в области предварительного просмотра.

Для работы загрузчика нам понадобится библиотека jQuery, а также созданный нами скрипт и стили:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script src="javascript.js"></script>
<link rel="stylesheet" type="text/css" href="style.css" />

Как всегда начинаем с HTML разметки, здесь ничего сложного нет:

   <!-- Область для перетаскивания -->
   <div id="drop-files" ondragover="return false">
      <p>Перетащите изображение сюда</p>
        <form id="frm">
           <input type="file" id="uploadbtn" multiple />
        </form>
   </div>

В самом верху страницы находится область для перетаскивания изображений, отмеченная пунктирной линией. А также кнопка выбора файлов, кому как удобнее. Событие ondragover работает пока перемещаемый файл над областью для перетаскивая.

Далее формируется область для предварительного просмотра изображений, а также кнопки для манипуляции и прогресс бар загрузки:

    <!-- Область предварительного просмотра -->
   <div id="uploaded-holder">
      <div id="dropped-files">
         <!-- Кнопки загрузить и удалить, а также количество файлов -->
         <div id="upload-button">
               <center>
                  <span>0 Файлов</span>
               <a href="#" class="upload">Загрузить</a>
               <a href="#" class="delete">Удалить</a>
                    <!-- Прогресс бар загрузки -->
                  <div id="loading">
                  <div id="loading-bar">
                     <div class="loading-color"></div>
                  </div>
                  <div id="loading-content"></div>
               </div>
                </center>
         </div>  
        </div>
   </div>

После того как выбранные изображения будут загружены появляется список-оповещение о выполненных загрузках:

   <!-- Список загруженных файлов -->
   <div id="file-name-holder">
      <ul id="uploaded-files">
         <h1>Загруженные файлы</h1>
      </ul>
   </div>

Вот так выглядит HTML разметка. Переходим к обработке событий загрузчика изображений.

Обработка событий

Начинается все с функции $(document).ready(). Каждая функция внутри нее будет выполняться как только DOM дерево документа будет готово:

$(document).ready(function() {
   // Весь последующий код javascript здесь
});

Начнем с объявления глобальных переменных нашего обработчика:

// В dataTransfer помещаются изображения которые перетащили в область div
jQuery.event.props.push('dataTransfer');
   
// Максимальное количество загружаемых изображений за одни раз
var maxFiles = 6;
   
// Оповещение по умолчанию
var errMessage = 0;
   
// Кнопка выбора файлов
var defaultUploadBtn = $('#uploadbtn');
   
// Массив для всех изображений
var dataArray = [];
   
// Область информер о загруженных изображениях - скрыта
$('#uploaded-files').hide();

Когда необходимые переменный объявлены, можно переходить к обработке происходящих событий на странице. А именно когда пользователь перетаскивает или выбирает изображение. Сначала разберем перетаскивание файла:

   // Метод при падении файла в зону загрузки
   $('#drop-files').on('drop', function(e) {
      // Передаем в files все полученные изображения
      var files = e.dataTransfer.files;
      // Проверяем на максимальное количество файлов
      if (files.length <= maxFiles) {
         // Передаем массив с файлами в функцию загрузки на предпросмотр
         loadInView(files);
      } else {
         alert('Вы не можете загружать больше '+maxFiles+' изображений!');
         files.length = 0; return;
      }
   });

Метод .on присоединяет обработчик события drop — перетаскивания, к блоку div (#drop-files). Что касается функции loadInView(files), о ней чуть ниже. Если количество выбранных файлов больше максимально установленного, появляется предупреждение и массив с изображениями очищается.

Теперь событие при выборе файлов с помощью кнопки:

// При нажатии на кнопку выбора файлов
   defaultUploadBtn.on('change', function() {
         // Заполняем массив выбранными изображениями
         var files = $(this)[0].files;
         // Проверяем на максимальное количество файлов
      if (files.length <= maxFiles) {
         // Передаем массив с файлами в функцию загрузки на предпросмотр
         loadInView(files);
              // Очищаем инпут файл путем сброса формы
              // Или вот так $("#uploadbtn").replaceWith( $("#uploadbtn").val('').clone( true ) );
              $('#frm').each(function(){
                this.reset();
              });

      } else {
         alert('Вы не можете загружать больше '+maxFiles+' изображений!');
         files.length = 0;
      }
   });

Он практически идентичен вышеописанному, но событие change.

Теперь можно перейти к описанию функции loadInView(files). Формирование области предварительного просмотра изображений:

// Функция загрузки изображений на предпросмотр
   function loadInView(files) {
      // Показываем обасть предпросмотра
      $('#uploaded-holder').show();
     
      // Для каждого файла
      $.each(files, function(index, file) {
                 
         // Несколько оповещений при попытке загрузить не изображение
         if (!files[index].type.match('image.*')) {
           
            if(errMessage == 0) {
               $('#drop-files p').html('Эй! только изображения!');
               ++errMessage
            }
            else if(errMessage == 1) {
               $('#drop-files p').html('Стоп! Загружаются только изображения!');
               ++errMessage
            }
            else if(errMessage == 2) {
               $('#drop-files p').html("Не умеешь читать? Только изображения!");
               ++errMessage
            }
            else if(errMessage == 3) {
               $('#drop-files p').html("Хорошо! Продолжай в том же духе");
               errMessage = 0;
            }

         } else {
         
         // Проверяем количество загружаемых элементов
         if((dataArray.length+files.length) <= maxFiles) {
            // показываем область с кнопками
            $('#upload-button').css({'display' : 'block'});
         }
         else { alert('Вы не можете загружать больше '+maxFiles+' изображений!'); return; }
         
         // Создаем новый экземпляра FileReader
         var fileReader = new FileReader();
            // Инициируем функцию FileReader
            fileReader.onload = (function(file) {
               
               return function(e) {
                  // Помещаем URI изображения в массив
                  dataArray.push({name : file.name, value : this.result});
                  addImage((dataArray.length-1));
               };
                 
            })(files[index]);
         // Производим чтение картинки по URI
         fileReader.readAsDataURL(file);
                     }
      });
      return false;
   }

С каждым файлом в переданном массиве files выполняем следующие действия. Сначала проверяем изображение это или нет. Если нет то выводим предупреждение. Если полученный файл является изображением, то снова проверяем не является ли загружаемый файл лишним. Для это уже к существующему количеству изображений в массиве прибавляем этот файл и проверяем. Если все удачно, то в дело вступает HTML5 file API. С помощью интерфейса FileReader производим асинхронное чтение файла. Который в последствии помещается в массив dataArray.

Для отображения изображений которые уже помещены в массив, используем функцию addImage() с параметром текущий индекс изображения в массиве.

// Процедура добавления эскизов на страницу
   function addImage(ind) {
      // Если индекс отрицательный значит выводим весь массив изображений
      if (ind < 0 ) {
      start = 0; end = dataArray.length;
      } else {
      // иначе только определенное изображение
      start = ind; end = ind+1; }
      // Оповещения о загруженных файлах
      if(dataArray.length == 0) {
         // Если пустой массив скрываем кнопки и всю область
         $('#upload-button').hide();
         $('#uploaded-holder').hide();
      } else if (dataArray.length == 1) {
         $('#upload-button span').html("Был выбран 1 файл");
      } else {
         $('#upload-button span').html(dataArray.length+" файлов были выбраны");
      }
      // Цикл для каждого элемента массива
      for (i = start; i < end; i++) {
         // размещаем загруженные изображения
         if($('#dropped-files > .image').length <= maxFiles) {
            $('#dropped-files').append('<div id="img-'+i+'" class="image" style="background: url('+dataArray[i].value+'); background-size: cover;"> <a href="#" id="drop-'+i+'" class="drop-button">Удалить изображение</a></div>');
         }
      }
      return false;
   }

Ключевым здесь является метод .append, который позволяет вставить указанное содержимое в соответствующий элемент. В нашем случае вставляем эскиз загруженного изображения в div (dropped-files). Эскиз это блок div, где id равен img-индекс изображения в массиве и в качестве фона используется загруженное изображение. А также ссылка на удаление только этого изображения из массива, ее id равен drop-индекс изображения в массиве.

Раз уж дошли до удаления определенного изображения из массива, стоит разобрать соответствующую функцию:

// Удаление только выбранного изображения
   $("#dropped-files").on("click","a[id^='drop']", function(e) {
        // Предотвращаем стандартное поведение
        e.preventDefault();
      // получаем название id
      var elid = $(this).attr('id');
      // создаем массив для разделенных строк
      var temp = new Array();
      // делим строку id на 2 части
      temp = elid.split('-');
      // получаем значение после тире тоесть индекс изображения в массиве
      dataArray.splice(temp[1],1);
      // Удаляем старые эскизы
      $('#dropped-files > .image').remove();
      // Обновляем эскизи в соответсвии с обновленным массивом
      addImage(-1);    
   });

C помощью селектора выбираем все элементы id которых начинается на drop. После чего получаем значение id полностью и разбиваем эту строку (метод split) на две части от символа тире. Вторая (т.е. правая от тире) часть является индексом изображения в массиве. Далее методом splice очищаем элемент (изображение) в массиве по указанному индексу, и методом remove удаляем все элементы эскизы в div (dropped-files). После чего, вызываем функцию addImage(-1) с отрицательным числом, это сделано для того чтобы из массива в область эскизов были снова выведены все оставшиеся изображения.

Теперь функция restartFiles, удаляет сразу все изображения.

// Функция удаления всех изображений
   function restartFiles() {
   
      // Установим бар загрузки в значение по умолчанию
      $('#loading-bar .loading-color').css({'width' : '0%'});
      $('#loading').css({'display' : 'none'});
      $('#loading-content').html(' ');
     
      // Удаляем все изображения на странице и скрываем кнопки
      $('#upload-button').hide();
      $('#dropped-files > .image').remove();
      $('#uploaded-holder').hide();
   
      // Очищаем массив
      dataArray.length = 0;
     
      return false;
   }

Здесь все просто длину массива dataArray приравниваем к 0, тем самым очищая его.

А вызывается она дважды один раз по нажатию на кнопку Удалить, а второй раз после загрузки изображений на сервер. Первый вариант:

$('#dropped-files #upload-button .delete').click(restartFiles);

И последнее событие это загрузка изображений на сервер.

// Загрузка изображений на сервер
   $('#upload-button .upload').click(function() {
     
      // Показываем прогресс бар
      $("#loading").show();
      // переменные для работы прогресс бара
      var totalPercent = 100 / dataArray.length;
      var x = 0;
     
      $('#loading-content').html('Загружен '+dataArray[0].name);
      // Для каждого файла
      $.each(dataArray, function(index, file) {
         // загружаем страницу и передаем значения, используя HTTP POST запрос
         $.post('upload.php', dataArray[index], function(data) {
         
            var fileName = dataArray[index].name;
            ++x;
           
            // Изменение бара загрузки
            $('#loading-bar .loading-color').css({'width' : totalPercent*(x)+'%'});
            // Если загрузка закончилась
            if(totalPercent*(x) == 100) {
               // Загрузка завершена
               $('#loading-content').html('Загрузка завершена!');
               
               // Вызываем функцию удаления всех изображений после задержки 1 секунда
               setTimeout(restartFiles, 1000);
            // если еще продолжается загрузка   
            } else if(totalPercent*(x) < 100) {
               // Какой файл загружается
               $('#loading-content').html('Загружается '+fileName);
            }
           
            // Формируем в виде списка все загруженные изображения
            // data формируется в upload.php
            var dataSplit = data.split(':');
            if(dataSplit[1] == 'загружен успешно') {
               $('#uploaded-files').append('<li><a href="images/'+dataSplit[0]+'">'+fileName+'</a> загружен успешно</li>');
                       
            } else {
               $('#uploaded-files').append('<li><a href="images/'+data+'. Имя файла: '+dataArray[index].name+'</li>');
            }
           
         });
      });
      // Показываем список загруженных файлов
      $('#uploaded-files').show();
      return false;
   });

По нажатию на кнопку Загрузить отображается прогресс бар, чтобы следить за ходом загрузки изображений. Данные по каждому изображению из массива dataArray передаются в PHP сценарий (файл upload.php), который загружается с помощью HTTP POST запроса ($.post). Это упрощенная версия HTTP (Ajax) запроса $.ajax. Данный файл после выполнения возвращает некоторые данные. C помощью уже известного метода split, разбиваем полученную строку на части. И если во второй части нам встречается строка «загружен успешно», значит формируем элемент списка загруженных файлов (имя файла в виде ссылки на него). После того как массив закончился и элементы списка готовы показываем весь список.

PHP сценарий загрузки

Последним шагом является загрузка изображения в папку на сервере. Приведенный PHP сценарий достаточно простой, при желании к нему можно «прикрутить» еще что-нибудь.

<?php
// Все загруженные файлы помещаются в эту папку
$uploaddir = 'images/';

// Вытаскиваем необходимые данные
$file = $_POST['value'];
$name = $_POST['name'];

// Получаем расширение файла
$getMime = explode('.', $name);
$mime = end($getMime);

// Выделим данные
$data = explode(',', $file);

// Декодируем данные, закодированные алгоритмом MIME base64
$encodedData = str_replace(' ','+',$data[1]);
$decodedData = base64_decode($encodedData);

// Вы можете использовать данное имя файла, или создать произвольное имя.
// Мы будем создавать произвольное имя!
$randomName = substr_replace(sha1(microtime(true)), '', 12).'.'.$mime;

// Создаем изображение на сервере
if(file_put_contents($uploaddir.$randomName, $decodedData)) {
   echo $randomName.":загружен успешно";
}
else {
   // Показать сообщение об ошибке, если что-то пойдет не так.
   echo "Что-то пошло не так. Убедитесь, что файл не поврежден!";
}
?>

Из массива POST извлекаются URI данные по изображению (имя и символьная строка идентифицирующая изображение). После чего получаем из имени изображения его расширении и формируем произвольное имя для создаваемого на сервере изображения. А символьную строка идентифицирующую изображение декодируем. Далее функцией file_put_contents (она последовательна успешным вызовам функций fopen(), fwrite() и fclose()) создаем изображение на сервере в указанной папке.

Этот сценарий возвращает строку с новым именем изображения и пояснением «загружен успешно» при успешном выполнении. Как раз над этой строкой (переменная data) мы и производили манипуляции в последнем событии.

Не стоит забывать, что папку куда помещаются изображения нужно создать вручную.

Схема файлов

Стили CSS разбирать не будем, так как они особой роли не играют, но без них все равно нельзя :) Поэтому лучше скачать ИСХОДНИКИ и разобраться со стилями самостоятельно (файл style.css).

На этом все. Загрузчик изображений на сервер с предпросмотром готов. Если у Вас остались какие-либо вопросы, оставляйте комментарии.

Дополнение

В этом дополнение напишу о том как можно реализовать хранение картинок в БД MySQL, точнее хранить будем только название каталога и имя файла. Это наверно самый распространенный метод, т.к. в любой момент можно изменить расположение картинок. Для хранения в БД следует создать отдельную таблицу, назовем ее images и добавим 4 поля:


Создадим новую таблицу для хранения картинок

И обеспечим следующую структуру таблицы, где id первичный ключ с автозаполнением:


Структура таблицы images

Решил также добавить дату загрузки файла, может понадобится при сортировке и тд.

Таблица готова, подготовим сценарий занесения данных по картинкам. Разместим его в том же файле, что и загрузка на сервер upload.php. В начало файла добавим строку подключения к серверу и выбор БД:

$db = mysql_connect ("servername","user","password");
mysql_select_db ("dbname",$db);

C подключением думаю сложностей не должно возникнуть :)

Теперь осталось произвести запись данных в таблицу images:

mysql_query ("INSERT INTO images (date,catalog,filename) VALUES (NOW(),'$uploaddir','$randomName')");

А добавляем эту строку сразу после загрузки файла на сервер. после этих небольших манипуляций файл upload.php примет вот такой вид:

// Создаем подключение к серверу
$db = mysql_connect ("servername","user","password");
// Выбираем БД
mysql_select_db ("dbname",$db);

// Все загруженные файлы помещаются в эту папку
$uploaddir = 'images/';

// Вытаскиваем необходимые данные
$file = $_POST['value'];
$name = $_POST['name'];

// Получаем расширение файла
$getMime = explode('.', $name);
$mime = end($getMime);

// Выделим данные
$data = explode(',', $file);

// Декодируем данные, закодированные алгоритмом MIME base64
$encodedData = str_replace(' ','+',$data[1]);
$decodedData = base64_decode($encodedData);

// Вы можете использовать данное имя файла, или создать произвольное имя.
// Мы будем создавать произвольное имя!
$randomName = substr_replace(sha1(microtime(true)), '', 12).'.'.$mime;

// Создаем изображение на сервере
if(file_put_contents($uploaddir.$randomName, $decodedData)) {
   // Записываем данные изображения в БД
   mysql_query ("INSERT INTO images (date,catalog,filename) VALUES (NOW(),'$uploaddir','$randomName')");
   echo $randomName.":загружен успешно";
}
else {
   // Показать сообщение об ошибке, если что-то пойдет не так.
   echo "Что-то пошло не так. Убедитесь, что файл не поврежден!";
}

А теперь то, ради чего затевалась БД. Страница показа изображений, так сказать наипростейшая галерея. Создадим файлик gallery.php и расположим его там же где и upload.php. В начале файла также производим подключение к серверу и выбор БД, а в теле документа добавляем следующий код:

<div class="main">
<?
$result = mysql_query ("SELECT * FROM images",$db);
if(!$result) { echo "Произошла ошибка подключения к серверу и БД, проверьте параметры подключения"; }
// Если количество записей больше нуля
if (mysql_num_rows($result) > 0)
{
   // Записываем полученные данные в массив
   $myrow = mysql_fetch_array ($result);
   // В цикле размещаем изображения на странице
   do {
                // В атрибуту src присваиваем путь до файла картинки
      echo "<img src='".$myrow['catalog'].$myrow['filename']."' />";
   }
   while ($myrow = mysql_fetch_array($result));
}
else
{
   // Сообщение о пустой таблице
   echo "<p>Информация по запросу не может быть извлечена, в таблице нет записей.</p>";
   exit();
}
?>
</div>

Чтобы изображения выводились в строку по три штуки, цикл вывода расположим в блоке div с шириной 900px, а изображениям присвоим относительное позиционирование и выравнивание по левому краю:

.main {
   width:900px;
   margin:0 auto;
   height:100%
}
.main img {
   position:relative;
   float:left;
   width:280px;
   height:180px;
   margin:10px;
}

Примечания:
1. При загрузке файлов используется передача данных методом post, поэтому стоит обратить внимание на директиву php.ini — post_max_size, отвечающий за максимальный размер передаваемых данных.
2. Примечание от Фидана Газимова: при использовании патча безопасности — Suhosin, необходимо отключить проверку длинны get, post запросов в файле suhosin.ini (в Debian файл расположен /etc/php5/conf.d/suhosin.ini):

  • suhosin.get.max_value_length = off
  • suhosin.post.max_value_length = off
  • suhosin.request.max_value_length = off

Чтобы оставаться в курсе свежих статей и уроков подписывайтесь на страницу ВКонтакте или добавляйте в круги на Google+. Спасибо!

Чтобы оставаться в курсе свежих статей и уроков подписывайтесь на еженедельную почтовую рассылку или на новостную ленту RSS. Спасибо!

  • Спасибо, как раз для одного проекта искал подобное решение, но так и не нашел тогда, и проект так и остался в планах)) только мне еще надо чтоб к картинке можно было описание прописывать, и чтоб все это в базе данных хронилось, и можно было выводить картинку с описание из базы))

    • Пожалуйста) ну насчет описания, можно сделать текстовый input к каждой картинке и при загрузке передавать эти данные в uploader.php. А в uploader.php сразу делать запись в базу, уже после создания картинки на сервере!

  • и кстати косяк есть небольшой… например я выбрал 2 картинки, он показывает их превьюшку. снова нажимаю на выбор файлов и добавляю еще 1 файл (не загружая первые 2 картинки на сервер), выбираю его, и загружаются превьюшки первых двух выбранных файлов и третьего, вместо только третьего…

    • странно, у меня такого не наблюдается. может при повторном открытии выбора файлов те 2 уже были выделены?

  • Вы могли бы описать как именно заносить данные о картинке в базу MySQL.
    Или куда именно вставлять запрос на занесения в базу.

    • Хорошо, в ближайшее время допишу этот урок.

    • Александр

      Спасибо! Буду очень ждать дополнения к этому уроку! Будет очень полезная информация для всех! Так как урок очень хороший и полезный!

    • Готово )

    • Александр

      Спасибо!)

  • А подскажи функцию для создание уменьшеньшенной копии картинки.

  • ainur101

    Имеется баг, вообщем, при загрузке файлов прогресс бар зависает, а файлы при этом корректно загружаются на сервер, однако сама процедура у пользователя незавершается. Заметил когда файлов больше 15.

    И еще как очистить историю загрузок? Например: выбрал файлы->загрузил, не обновляя страницу выбираю еще пару фоток, а тут хоп превью прошлых фотографии.

    • Насчет истории, можно сбросить форму
      $(‘#frm’).each(function() { this.reset(); });
      т.е. инпут надо в тег добавить

  • ainur101

    При 11 файлах,   видимо что то вот тут 

    var totalPercent = 100 / dataArray.length;
    var x = 0;

  • Pervik66

    Добрый день, всё работает. Только как сделать, чтобы например 10 фотографий когда добавляешь пути фотографий записались в одно поле определённой таблицы .
    Помогите пожалуйста!

  • tm-media

    Как быть с большими фотографиями? Не подскажите необходимые настройки в php.ini? А так же способомы оптимизации, т.к. на машинах с ОЗУ до 1 Гб браузер просто зависает(~50 мб фотографии)

    • для того чтобы большие изображения загружать в php.ini надо увеличить размер данных передаваемых в POST запросе
      post_max_size
      а также по экспериментируйте с memory_limit в том же php.ini, возможно не будет зависать

  • Pervik66

    Ну что, кто-нибудь поможет с решением проблемы.Чтобы все фотографии, которые закинул добавить в поле с одним id например через запятую!

    • можно сделать так, убрать из файла uploader.php запись в БД, а вынести ее в отдельный файл (допустим insert.php). Также придется немного изменить яваскрипт при загрузке. Создать строковую переменную

      var str = «»;
      когда загружаем картинки на сервер в цикле .each нам возвращается переменная data мы ее еще делим на 2 части так вот, после каждого ее получения добавляем к str новое название — после строки var dataSplit = data.split(‘:’);
      str = str + «,» + dataSplit[0]; 
      когда цикл закончился поместить эту строку в новый массив :
      var newArray = [];
      newArray.push({name : str});
      Теперь в пост запросе передаем это в пхп файл:$.post(‘insert.php’, newArray[0], function() {});
      а в пхп принять так:
       $name = $_POST[‘name’]; 
      mysql_query («INSERT INTO images (filename) VALUES (‘$name’)»);
       
      Подходит???

    • Pervik66

      Спасибо Дмитрий попробую, как будет свободное время.Хотя с ява скриптами не знаком.(((

    • Pervik66

       Был бы благодарен если бы вы выложили вариант javascripta где все фотографии передавались бы одним массивом, ну т.е. то что вы написали выше.Так как совсем далёк от java. Не сочтите за наглость пожалуйста.

    • Вот исправил как описано выше, только не забудьте увеличить длину поля filename в БД раз все в одну строку пишется и в файле insert.php исправить подключение к БД. Ну соответственно придется поправить вывод в галерею. СКАЧАТЬ  Если что пишите =)

  • Pervik66

    Ну что, кто-нибудь поможет с решением проблемы.Чтобы все фотографии, которые закинул добавить в поле с одним id например через запятую!

  • Pervik66

    Дмитрий огромное спасибо.Респект и уважуха ВАМ! Единственный нормальный человек, который по просьбе незнакомого человека, доработал свой скрипт под чужие нужды бесплатно(за идею).
    Всё-таки бывают добрые люди.Обязательно поставлю на Вас ссылку.

    • И Вам Спасибо, за такой теплый комментарий))) За ссылку буду благодарен =)

  • Nickolka

    Спасибо большое!!! очень понадобилось мне

  • Сергей

    Не пойму в Explorer 9 он не работает?

  • Makssimka

    Дмитрий спасибо за статью! У меня есть такой вопрос, на эскизах я сделал элементы checkbox и select соответственно каждому изображению свои, вот код :
    $(‘#dropped-files’).append(‘ АвтоПрирода Удалить изображение‘);
    Как теперь данные из них отправить в php сценарий загрузки? Может вопрос конечно глупый но я только делаю первые шаги!

    • Здравствуйте, для начала изменим состав массива для изображений добавим еще 2 поля, т.е. вот так:

      dataArray.push({name : file.name, value : this.result, check : null, sel : null});

      я изменил Ваш код немного, добавил атрибут value, его значение будем передавать:

      $(‘#dropped-files’).append(‘ АвтоПрирода Удалить изображение‘);

      ну а теперь когда перебираем все картинки, дописываем в новые поля не достающие данные (это после строки $.each(dataArray, function(index, file) {):

      dataArray[index].check = $(‘#openCatal-‘+index+’:checked’).val();
      dataArray[index].sel = $(‘#selectOpen-‘+index+»).val();

      ну а в php их остается только принять =)

    • Makssimka

      Спасибо буду пробовать!

    • Пожалуйста)

  • Юрий

    В ie8 тоже не работает/ Выдает ошибку ‘length’ is null or not an object. В скрипте это соответствует if (files.length <= maxFiles) {

  • Makssimka

    А можно еще вопрос? Допустим я передаю на страницу с загрузчиком идентификатор альбома методом get:
    ?idAlbum=8
    var idAlbum = $_GET[‘idAlbum’];
    А также у нас есть имя пользователя в сессиях:
    $_SESSION[‘login’]
    И внесем их в яваскрипт:
    echo ‘$idAlbum = » ‘. idAlbum . ‘ »
    и т.д.
    Можно их как-нибудь внести в скрипт и отправить на сервер! Заранее спасибо!

    • в index.php получаем из гет массива как Вы написали и передаем сразу в скрипт:

      < ?
      $id = $_GET['id'];
      $login = $_SESSION['login'];
      echo 'var idalbum = «‘.$id.'»;’;
      echo ‘var login= «‘.$login.'»;’;

      ? >

      Можно добавить в массив к картинка или так:

      $.post(‘upload.php’, {mas : dataArray[index], ida : idalbum, log : login}, function(data) {..}

      Ну и в upload.php тогда немного по другому:

      $mas = $_POST[‘mas’];
      $idalbum = $_POST[‘ida’];
      $login = $_POST[‘log’];

      $file = $mas[‘value’];
      $name = $mas[‘name’];
      $check = $mas[‘check’];
      $sel = $mas[‘sel’];

      Подходит?

    • Makssimka

      Сейчас буду Пробовать отходил просто! Спасибо!

    • Makssimka

      Все получилось, еще раз спасибо!

    • Пожалуйста, обращайтесь если что)

  • Николай

    Спасибо за эту замечательную статью!
    Есть одна проблема.в
    $(«a[id^=’drop’]»).live(‘click’…)
    в jQuery версии 1.9 live убрали и заменили его на on(‘click’,…)
    с которым не работает удаление файла
    что делать, куда бежать?

    • Николай

      Простите за глупый вопрос. Сам спросил, сам отвечу.
      $(«a[id^=’drop’]»).live(‘click’, function() { …
      меняем на
      $(document).on(‘click’,»a[id^=’drop’]», function() { …

    • И Вам спасибо, почаще бы такие вопросы появлялись =) Урок пофиксил!

  • Николай

    1)Ув. Дмитрий спасибо за статью не подскажите ли как можно отчистить только часть формы,т.е мне не подходит код:
    $(‘#frm’).each(function(){
    this.reset();
    });
    Потому что кроме картинок есть еще и текстовые поля,которые при добавлении новых фото просто стераются ,а если я убираю эту очистку формы то нельзя второй раз в превью загрузить точно такую же картинку

    2)И еще обнаружил небольшой баг,когда нажимаешь удалить изображение веб-страница уходит вверх(если вы вставите эту форму загрузки в самый низ страницы то увидете),чтобы этого не было я сделал так:
    $(«#dropped-files»).on(«click»,»a[id^=’drop’]», function(e) {
    e.preventDefault();

    Правильно ли это?Буду рад ответу

    • 1) Вот такой вариант очистки только поля file, поиск по id:

      $(«#uploadbtn»).replaceWith( $(«#uploadbtn»).val(»).clone( true ) );

      2) Ваше решение правильное.