Статьи

Загрузка файлов с помощью AJAX

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

О, конечно, были взломы; но если вы похожи на меня и чувствуете себя грязным каждый раз, когда вы iframe , вам это очень понравится. Присоединяйся ко мне после прыжка!

Если вы ищете быстрое решение, на Envato Market есть большая коллекция скриптов и приложений для загрузки файлов .

Это средство загрузки файлов HTML5 особенно изящно — вы можете легко добавлять файлы, перетаскивая их или щелкая. Все файлы будут загружены через AJAX или могут быть добавлены в форму, и файлы могут быть переименованы перед загрузкой. Отличное, быстрое решение, если это то, что вы ищете!


Почему бы нам не покончить с плохими новостями?

Это не работает в каждом браузере. Однако, с некоторым прогрессивным улучшением (или каким-либо другим текущим модным словом), у нас будет страница загрузки, которая будет работать обратно в IE6 (хотя и без битов AJAXy).

Наша загрузка AJAX будет работать, пока доступны данные FormData ; в противном случае пользователь получит нормальную загрузку.

В нашем проекте есть три основных компонента.

  • multiple атрибут в элементе input файла.
  • Объект FileReader из нового Файлового API.
  • Объект FormData из XMLHttpRequest2.

Мы используем атрибут multiple чтобы позволить пользователю выбрать несколько файлов для загрузки (загрузка нескольких файлов будет работать нормально, даже если FormData недоступен). Как вы увидите, FileReader позволяет нам показывать миниатюры пользовательских файлов, которые они загружают (мы ожидаем изображения).

Ни одна из наших трех функций не работает в IE9, поэтому все пользователи IE получат нормальную загрузку (хотя я понимаю, что поддержка `FileReader` доступна в IE10 Dev Preview 2). FileReader не работает в последней версии Safari (5.1), поэтому они не получат эскизы, но получат загрузку AJAX и сообщение с подтверждением. Наконец, Opera 10.50 имеет поддержку FileReader но не поддержку FormData , поэтому они будут получать эскизы, но обычные загрузки.

С этим из пути, давайте получить кодирование!


Давайте начнем с некоторой базовой разметки и стиля. Конечно, это не основная часть этого урока, я не буду относиться к вам как к новичку.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang=»en»>
<head>
  <meta charset=»UTF-8″ />
  <title>HTML5 File API</title>
  <link rel=»stylesheet» href=»style.css» />
</head>
<body>
  <div id=»main»>
    <h1>Upload Your Images</h1>
    <form method=»post» enctype=»multipart/form-data» action=»upload.php»>
      <input type=»file» name=»images» id=»images» multiple />
      <button type=»submit» id=»btn»>Upload Files!</button>
    </form>
 
    <div id=»response»></div>
    <ul id=»image-list»>
 
    </ul>
  </div>
 
  <script src=»https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js»></script>
  <script src=»upload.js»></script>
</body>
</html>

Довольно простой, а? У нас есть форма, которая публикует upload.php , который мы рассмотрим через секунду, и один элемент ввода типа file . Обратите внимание, что он имеет логический атрибут multiple , который позволяет пользователю выбирать несколько файлов одновременно.

Это действительно все, что можно увидеть здесь. Давайте двигаться дальше.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
body {
  font: 14px/1.5 helvetica-neue, helvetica, arial, san-serif;
  padding:10px;
}
 
h1 {
  margin-top:0;
}
 
#main {
  width: 300px;
  margin:auto;
  background: #ececec;
  padding: 20px;
  border: 1px solid #ccc;
}
 
#image-list {
  list-style:none;
  margin:0;
  padding:0;
}
#image-list li {
  background: #fff;
  border: 1px solid #ccc;
  text-align:center;
  padding:20px;
  margin-bottom:19px;
}
#image-list li img {
  width: 258px;
  vertical-align: middle;
  border:1px solid #474747;
}

Абсолютно нет шокеров здесь.


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

01
02
03
04
05
06
07
08
09
10
<?php
 
foreach ($_FILES[«images»][«error»] as $key => $error) {
  if ($error == UPLOAD_ERR_OK) {
    $name = $_FILES[«images»][«name»][$key];
    move_uploaded_file( $_FILES[«images»][«tmp_name»][$key], «uploads/» . $_FILES[‘images’][‘name’][$key]);
  }
}
 
echo «<h2>Successfully Uploaded Images</h2>»;

Имейте в виду, что это были первые строки PHP, которые я написал за год ( я парень из Ruby ). Вы, вероятно, должны сделать немного больше для безопасности; однако мы просто следим за тем, чтобы ошибок при загрузке не было. Если это так, мы используем встроенный move_uploaded_file чтобы переместить его в папку uploads . Не забудьте убедиться, что папка доступна для записи.

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

Вот как выглядит наш мини-проект:

Стилизованная форма

Но давай, это 2011 год: мы хотим большего. Вы заметите, что мы связали jQuery и файл upload.js . Давайте сейчас раскроем это.


Давайте не будем тратить время зря!

Вот с чего мы начнем. Мы создаем две переменные: input — наш элемент ввода файла; formdata будет использоваться для отправки изображений на сервер, если браузер поддерживает это. Мы инициализируем его как false и затем проверяем, поддерживает ли браузер FormData ; Если это так, мы создаем новый объект FormData . Кроме того, если мы можем отправить изображения с помощью AJAX, нам не нужна кнопка «Загрузить изображения!», Поэтому мы можем ее скрыть. Почему нам это не нужно? Что ж, мы собираемся автоматически загружать изображения сразу после того, как пользователь их выберет.

Остальная часть JavaScript войдет в вашу анонимную функцию самовызвания. Затем мы создадим небольшую вспомогательную функцию, которая будет показывать изображения, как только они появятся в браузере:

Функция принимает один параметр: источник изображения (скоро мы увидим, как мы это получим). Затем мы просто находим список в нашей разметке и создаем элемент списка и изображение. Мы устанавливаем источник изображения в качестве источника, который мы получили, помещаем изображение в элемент списка и помещаем элемент списка в список. Вуаля!

Затем мы должны взять изображения, отобразить их и загрузить. Как мы уже говорили, мы сделаем это, когда событие onchange будет onchange элемента input.

Нам не нужно беспокоиться о патентованной модели событий IE, потому что IE9 + поддерживает стандартную функцию addEventListener.

Это еще не все, но давайте начнем с этого. Во-первых, нам не нужно беспокоиться о патентованной модели событий IE, потому что IE9 + поддерживает стандартную функцию addEventListener (а IE9 и ниже не поддерживают наши новые функции).

Итак, что мы хотим сделать, когда пользователь выбрал файлы? Сначала мы создадим несколько переменных. Единственный важный сейчас — это len = this.files.length . Файлы, которые выбрал пользователь, будут доступны из объекта this.files . Сейчас нас интересует только свойство length , поэтому мы можем зацикливаться на файлах…

… это именно то, что мы делаем дальше. Внутри нашего цикла мы устанавливаем текущий файл в file для удобства доступа. Следующее, что мы делаем, это подтверждаем, что файл является изображением. Мы можем сделать это, сравнивая свойство type с регулярным выражением. Мы ищем тип, который начинается с «изображения» и сопровождается чем угодно. (Двойной удар впереди преобразует результат в логическое значение.)

Итак, что нам делать, если у нас на руках изображение?

Мы проверяем, поддерживает ли браузер создание объектов FileReader . Если это произойдет, мы создадим один.

Вот как мы используем объект FileReader : мы собираемся передать наш file объект методу reader.readAsDataURL . Это создает URL-адрес данных для загруженного изображения. Однако это не работает так, как вы могли бы ожидать. URL-адрес данных не передается обратно из функции. Вместо этого URL-адрес данных будет частью объекта события.

Имея это в виду, нам нужно зарегистрировать функцию reader.onloadend события reader.onloadend . Эта функция принимает объект события, по которому мы получаем URL-адрес данных: он находится в e.target.result (да, e.target — это объект reader , но у меня были проблемы при использовании reader вместо e.target внутри этой функции) , Мы просто собираемся передать этот URL-адрес данных нашей функции showUploadedItem (которую мы написали выше).

Далее мы проверяем объект formdata . Помните, что если браузер поддерживает FormData , formdata будет объектом FormData ; в противном случае это будет false . Итак, если у нас есть объект FormData , мы собираемся вызвать метод append . Цель объекта FormData — хранить значения, которые вы отправляете через форму; Итак, метод append просто принимает ключ и значение. В нашем случае наш ключ — images[] ; добавляя квадратные скобки в конец, мы проверяем, что каждый раз, добавляя другое значение, мы фактически append его в этот массив, вместо того, чтобы перезаписывать свойство image .

Мы почти закончили. В нашем цикле for мы отобразили каждое из изображений для пользователя и добавили их в объект formdata . Теперь нам просто нужно загрузить изображения. Вне цикла for , вот последняя часть нашей головоломки:

Опять же, мы должны убедиться, что у нас FormData поддержка FormData ; если мы этого не сделаем, кнопка «Загрузить файлы!» будет видна, и именно так пользователь будет загружать фотографии. Однако, если у нас FormData поддержка FormData , мы позаботимся о загрузке через AJAX. Мы используем jQuery для обработки всех странностей AJAX в разных браузерах.

Вы, вероятно, знакомы с методом jQuery $.ajax : вы передаете ему объект параметров. Свойства url , type и success должны быть очевидны. Свойство data является нашим объектом formdata . Обратите внимание на эти свойства processData и contentType . Согласно документации jQuery, processData по умолчанию имеет значение true и будет обрабатывать и преобразовывать данные в строку запроса. Мы не хотим этого делать, поэтому мы устанавливаем это в false . Мы также устанавливаем для contentType значение false чтобы гарантировать, что данные поступают на сервер так, как мы ожидаем.

Вот и все. Теперь, когда пользователь загружает страницу, он видит это:

Учебное изображение

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

Учебное изображение

И изображения были загружены:

Учебное изображение

Загрузка файлов через AJAX — это здорово, и это здорово, что эти новые технологии поддерживают это без необходимости длительных хаков. Если у вас есть какие-либо вопросы о том, что мы сделали здесь, нажмите на эти комментарии! Большое спасибо за чтение!

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

Мы создали полное руководство, которое поможет вам изучить JavaScript , независимо от того, начинаете ли вы как веб-разработчик или хотите изучать более сложные темы.