Перетащите файл сюда или загрузите вручную

Обновлено: 27.06.2024

Краткое резюме ↬ В этой статье мы будем использовать «ванильный» JavaScript ES2015+ (без фреймворков или библиотек) для завершения этого проекта, и предполагается, что у вас есть практические знания JavaScript в браузере. Этот пример должен быть совместим со всеми вечнозелеными браузерами, а также с IE 10 и 11.

Известно, что входные данные для выбора файлов трудно стилизовать так, как хотят разработчики, поэтому многие просто скрывают его и вместо этого создают кнопку, которая открывает диалоговое окно выбора файла. Однако в настоящее время у нас есть еще более причудливый способ выбора файлов: перетаскивание.

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

В этой статье мы будем использовать «ванильный» JavaScript ES2015+ (без фреймворков или библиотек) для завершения этого проекта, и предполагается, что у вас есть практические знания JavaScript в браузере. Этот пример — за исключением синтаксиса ES2015+, который можно легко изменить на синтаксис ES5 или транспилировать Babel — должен быть совместим со всеми вечнозелеными браузерами, а также с IE 10 и 11.

Вот краткий обзор того, что вы будете делать:

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

События перетаскивания

Первое, что нам нужно обсудить, — это события, связанные с перетаскиванием, поскольку они являются движущей силой этой функции. Всего существует восемь событий, связанных с перетаскиванием браузером: drag, dragend, dragenter, dragexit, dragleave, dragover, dragstart и drop. Мы не будем рассматривать их все, потому что drag , dragend , dragexit и dragstart запускаются для перетаскиваемого элемента, и в нашем случае мы будем перетаскивать файлы из нашей файловой системы, а не элементы DOM. , поэтому эти события никогда не всплывут.

Если вам интересно узнать о них, вы можете прочитать документацию об этих событиях на MDN.

Познакомьтесь с потрясающими онлайн-семинарами по внешнему интерфейсу и пользовательскому интерфейсу с практическими выводами, сеансами в прямом эфире, видеозаписями и дружескими вопросами и ответами. О дизайн-системах, CSS/JS и UX. С Кэри Фишер, Стефаном Баумгартнером и многими другими.

Как и следовало ожидать, вы можете зарегистрировать обработчики событий для этих событий так же, как вы регистрируете обработчики событий для большинства событий браузера: через addEventListener .

Вот небольшая таблица, описывающая, что делают эти события, с использованием dropArea из примера кода, чтобы сделать язык более понятным:

< tr>
СобытиеКогда оно срабатывает?
dragenter Перетащенный элемент перетаскивается над dropArea, что делает его целью события перетаскивания, если пользователь перетащит его туда.
dragleave Перетащенный элемент перетаскивается из dropArea в другой элемент, вместо этого он становится целью события перетаскивания.
dragover Каждые несколько сотен миллисекунд, пока перетаскиваемый элемент находится над dropArea и движется.
drop Пользователь отпускает кнопку мыши, перетаскивая перетаскиваемый элемент в dropArea.

Обратите внимание, что перетаскиваемый элемент перетаскивается на дочерний элемент dropArea , dragleave срабатывает на dropArea , а dragenter срабатывает на этом дочернем элементе, поскольку он является новой целью . Событие drop будет распространяться до dropArea (если распространение не будет остановлено другим обработчиком событий до того, как оно попадет туда), поэтому оно по-прежнему будет срабатывать в dropArea, несмотря на то, что оно не является целью события.

Также обратите внимание, что для создания пользовательских взаимодействий перетаскивания вам потребуется вызвать event.preventDefault() в каждом из прослушивателей для этих событий. Если вы этого не сделаете, браузер в конечном итоге откроет перетащенный вами файл, а не отправит его обработчику события перетаскивания.

Настройка нашей формы

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

Довольно простая структура. Вы можете заметить обработчик onchange на входе. Мы рассмотрим это позже. Также было бы неплохо добавить действие в форму и кнопку отправки, чтобы помочь тем людям, у которых не включен JavaScript. Затем вы можете использовать JavaScript, чтобы избавиться от них для более чистой формы.В любом случае вам потребуется сценарий на стороне сервера, чтобы принять загрузку, будь то что-то, разработанное внутри компании, или вы используете такой сервис, как Cloudinary, который сделает это за вас. Кроме этих заметок, здесь нет ничего особенного, так что давайте добавим несколько стилей:

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

Добавление функции перетаскивания

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

Теперь добавим несколько событий. Мы начнем с добавления обработчиков ко всем событиям, чтобы предотвратить поведение по умолчанию и предотвратить всплытие событий выше необходимого:

Нам пришлось использовать как перетаскивание , так и перетаскивание для выделения из-за того, что я упоминал ранее. Если вы начнете наводить курсор непосредственно на dropArea, а затем наведите указатель мыши на один из его дочерних элементов, то будет запущен dragleave, а выделение будет удалено. Событие dragover запускается после событий dragenter и dragleave, поэтому выделение будет добавлено обратно в dropArea до того, как мы увидим, что оно было удалено.

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

Теперь все, что нам нужно сделать, это выяснить, что делать, если некоторые файлы удалены:

Это не приближает нас к завершению, но делает две важные вещи:

  1. Демонстрирует, как получить данные для удаленных файлов.
  2. Возвращает нас к тому же месту, где был ввод файла с его обработчиком onchange: ожидание handleFiles .

Имейте в виду, что files — это не массив, а FileList. Итак, когда мы реализуем handleFiles , нам нужно будет преобразовать его в массив, чтобы упростить его итерацию:

Это было разочаровывающим. Давайте перейдем к uploadFile для настоящего содержательного материала.

В зависимости от того, как настроен ваш сервер, вы можете проверить различные диапазоны номеров состояния, а не только 200, но для наших целей это сработает.

Дополнительные функции

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

Предварительный просмотр изображения

Есть несколько способов сделать это: вы можете подождать, пока изображение не будет загружено, и попросить сервер отправить URL-адрес изображения, но это означает, что вам нужно подождать, а изображения иногда могут быть довольно большими. . Альтернативой, которую мы рассмотрим сегодня, является использование API FileReader для данных файла, которые мы получили из события перетаскивания. Это асинхронно, и в качестве альтернативы вы можете использовать FileReaderSync, но мы можем попытаться прочитать несколько больших файлов подряд, так что это может надолго заблокировать поток и действительно испортить работу. Итак, давайте создадим функцию previewFile и посмотрим, как она работает:

Здесь мы создаем новый FileReader и вызываем для него readAsDataURL с объектом File. Как уже упоминалось, это асинхронно, поэтому нам нужно добавить обработчик события onloadend, чтобы получить результат чтения. Затем мы используем базовый URL-адрес данных 64 в качестве источника для нового элемента изображения и добавляем его в элемент галереи. Теперь нужно сделать только две вещи: добавить элемент галереи и убедиться, что файл previewFile действительно вызывается.

Сначала добавьте следующий HTML-код сразу после конца тега формы:

Ничего особенного; это просто див. Для него уже заданы стили и изображения в нем, так что делать там больше нечего. Теперь давайте изменим функцию handleFiles на следующую:

Есть несколько способов сделать это, например, с помощью композиции или одного обратного вызова forEach, который запускал в нем uploadFile и previewFile, но и это работает. И при этом, когда вы перетаскиваете или выбираете некоторые изображения, они должны почти мгновенно отображаться под формой. Самое интересное в этом то, что в некоторых приложениях вы можете не захотеть загружать изображения, а вместо этого хранить их URL-адреса данных в локальном хранилище или каком-либо другом кэше на стороне клиента, чтобы приложение могло получить к нему доступ позже. Лично я не могу придумать ни одного удачного варианта его использования, но готов поспорить, что такие есть.

Отслеживание прогресса

Если что-то может занять некоторое время, индикатор выполнения может помочь пользователю понять, что на самом деле происходит прогресс, и указать, сколько времени потребуется для завершения. Добавить индикатор прогресса довольно просто благодаря тегу прогресса HTML5. Давайте начнем с того, что на этот раз добавим это в HTML-код.

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

Тогда нам также нужно обновить наши функции. Мы переименуем progressDone в updateProgress и изменим их следующим образом:

Теперь initializeProgress инициализирует массив длиной, равной numFiles, заполненный нулями, что означает, что каждый файл заполнен на 0 %. В updateProgress мы узнаем, прогресс какого изображения обновляется, и меняем значение этого индекса на указанный процент. Затем мы вычисляем общий процент выполнения, взяв среднее значение всех процентов, и обновляем индикатор выполнения, чтобы отразить рассчитанную сумму. Мы по-прежнему вызываем initializeProgress в handleFiles так же, как и в примере с выборкой, так что теперь все, что нам нужно обновить, это uploadFile для вызова updateProgress .

Первое, что нужно отметить, это то, что мы добавили параметр i. Это индекс файла в списке файлов. Нам не нужно обновлять handleFiles для передачи этого параметра, потому что он использует forEach, который уже дает индекс элемента в качестве второго параметра для обратных вызовов. Мы также добавили прослушиватель событий progress в xhr.upload, чтобы мы могли вызывать updateProgress с прогрессом. Объект события (обозначаемый в коде как e) имеет две соответствующие части информации о нем: загрузил, который содержит количество байтов, которые были загружены до сих пор, и итог, который содержит общее количество байтов в файле.

|| Там находится 100 штук, потому что иногда, если есть ошибка, e.loaded и e.total будут равны нулю, что означает, что вычисление выйдет как NaN , поэтому вместо этого используется 100, чтобы сообщить, что файл готов. Вы также можете использовать 0 . В любом случае ошибка будет отображаться в обработчике readystatechange, чтобы вы могли сообщить о ней пользователю. Это просто для предотвращения создания исключений при попытке выполнить математические операции с NaN .

Заключение

Познакомьтесь с кратким учебным пособием о том, как создать простую загрузку файлов методом перетаскивания с помощью Javascript и HTML. Забудьте об этих старых скучных загрузках «выберите файл». Каменный век Интернета давно закончился, и пришло время создавать более захватывающие загрузки. Загрузку с помощью перетаскивания на самом деле не так уж сложно реализовать, и мы можем сделать это с помощью простого ванильного Javascript. Читайте дальше, чтобы узнать, как это сделать!

ⓘ Я включил zip-файл со всем исходным кодом в начале этого руководства, поэтому вам не нужно копировать и вставлять все… Или если вы просто хотите сразу погрузиться.

СОДЕРЖАНИЕ

СКАЧАТЬ И ДЕМО

Во-первых, вот ссылка для загрузки примера кода, как и было обещано.

СКАЧАТЬ ПРИМЕР КОДА

Нажмите здесь, чтобы загрузить исходный код в виде zip-файла. Я выпустил его под лицензией MIT, так что не стесняйтесь использовать его, если хотите.

БЫСТРЫЕ ЗАМЕЧАНИЯ

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

ЗАГРУЗИТЬ ДЕМО ПЕРЕТАСКИВАНИЕМ

  1. Капитан Очевидность, загрузите CSS и Javascript.
  2. Определить пустой

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

КАК РАБОТАЕТ ЗАГРУЗКА УДАЛЕНИЕМ ПЕРЕТАСКИВАНИЯ

Хорошо, теперь давайте подробно рассмотрим, как работает загрузчик с помощью перетаскивания.

ЧАСТЬ A) ИНИЦИАЛИЗАЦИЯ ЗАГРУЗЧИКА

Вы уже знаете это, мы вызываем ddup.init(), чтобы прикрепить загрузчик к HTML

  • (A1) Обратите внимание на экземпляры instance.upqueue и instance.uplock, они потребуются позже для очереди загрузки.
  • (A2) Мы создаем еще 2 раздела внутри цели:

ЧАСТЬ B) ОЧЕРЕДЬ ЗАГРУЗКИ

  • Создайте соответствующий статус загрузки файла HTML.
  • Отправьте файл в instance.upqueue .

Причина этого «трюка» проста: AJAX асинхронный. Будет плохо, если пользователь сбросит сотни файлов, а серверу придется обрабатывать сотни параллельных загрузок сразу. Поэтому вместо параллельной загрузки мы будем использовать instance.upqueue и загружать по очереди.

ЧАСТЬ C) ЗАГРУЗКА AJAX

Наконец, функция ddup.go() выполняет фактическую загрузку. Здесь ничего особенного, просто старый добрый AJAX. Кроме того, помните, что вы использовали флаг uplock для ограничения по одному?Просто обратите внимание на то, как блокировка срабатывает в начале функции и разблокируется, когда загрузка заканчивается.

ПОЛЕЗНЫЕ ИНФОРМАЦИИ И ССЫЛКИ

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

КАК НА СЕРВЕРНОЙ СТОРОНЕ!?

Все зависит от вас, чтобы обрабатывать загрузку на стороне сервера, но если вы используете PHP, вот очень простой обработчик загрузки:

ПРОВЕРКА СОВМЕСТИМОСТИ

Это руководство по загрузке AJAX с помощью перетаскивания будет работать во всех современных браузерах.

ССЫЛКИ И ССЫЛКИ

КОНЕЦ

Спасибо за чтение, мы подошли к концу этого руководства. Я надеюсь, что это решило ваши проблемы с загрузкой, и если у вас есть что добавить к этому руководству, пожалуйста, не стесняйтесь комментировать ниже. Удачи и удачного кодирования!

34 мысли о «Простая загрузка файлов с помощью перетаскивания с помощью JS HTML5 (бесплатная загрузка)»

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

Здравствуйте! Спасибо за создание этого очень полезного инструмента. Я только что попробовал это на веб-сайте, которым я управляю, и он работает отлично. Как и ожидалось, он загружает файлы в тот же каталог, что и файлы dd-upload.

Мне интересно, могу ли я изменить dd-upload.js, чтобы указать другую папку назначения для загрузки. Пример: в настоящее время у меня есть все файлы dd-upload в каталоге с именем «upload_test», который находится в корневой папке веб-сайта («htdocs»). Я хочу, чтобы скрипт помещал загруженные файлы в отдельную папку (называемую «еженедельное аудио»), которая также находится в папке «htdocs».

Я предполагаю, что для этого мне потребуется изменить/добавить раздел «C3 UPLOAD DATA», но я не уверен, какую строку кода использовать. Мы будем очень признательны за любую помощь, которую вы можете оказать.

Большое спасибо,
Кен Камберлидж
Норвич, Великобритания

EDIT: весь виджет был переписан.

Привет. Не могли бы вы расширить этот ответ. виджет обновлен или код выше?
Я пытался добавить этот код между разными строками в категории C3, но безуспешно.

Отредактировано. См. выше.

Спасибо за это руководство.
Я не знаком с AJAX, поэтому не понимаю, даже если все остальное работает нормально, когда он интегрирован в большую форму с тем же файлом, обрабатывающим загрузку ( форма action="" ), при отправке содержимое формы дублируется внутри исходной страницы столько раз, сколько есть файлов для загрузки. Точно так же, как если бы цель отправки формы находилась в новом iframe для каждого файла, а не загружалась на пустой странице.
Есть ли способ предотвратить это и заставить форму вести себя более традиционно?

Не используйте iframe — устаревший и запутанный метод. Вернитесь к основам, не пропускайте их.

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

В этой статье мы изучим, как выполнять загрузку файлов методом перетаскивания с помощью JavaScript и PHP.

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

Загрузка файла перетаскиванием

Зачем нужна функция загрузки файлов с помощью перетаскивания?

Мы всегда стремимся к тому, чтобы сайт был удобнее для пользователей. Предоставление функции перетаскивания для загрузки файлов является простым в использовании вариантом для пользователей. Многие популярные веб-сайты, такие как Facebook и WordPress, уже используют это поведение.

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

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

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

Интегрировать загрузчик файлов методом перетаскивания

Для начала давайте сначала напишем код HTML. В следующем HTML-коде будет контейнер для загрузки файла. Он также включает файлы CSS и JS, которые я создам на следующих этапах.

В приведенном выше HTML-коде я использовал 2 события — ondrop и onclick. Я определю их в файле custom.js. Перед этим добавим CSS в файл style.css.

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

Для обработки этого сценария добавьте следующий код в файл custom.js.

Приведенный выше код JavaScript автоматически определяет параметры (перетаскивание или просмотр), выбранные для загрузки файла. Наконец, функция ajax_file_upload() берет объект файла и передает его вызову Ajax. Получив ответ, он отображает загруженное изображение в DOM. Если вы не загружаете изображения, закомментируйте эту часть innerHTML.

Загрузить файл на сервер

Наконец, давайте напишем в файле Ajax фактический код, который загружает файл на сервер. Создайте файл с именем ajax.php и добавьте в него приведенный ниже код.

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

Надеюсь, вы понимаете, как добавить загрузку файлов методом перетаскивания с помощью PHP и JavaScript. Дайте мне знать ваши мысли и предложения в комментарии ниже.

Статьи по теме

Если вам понравилась эта статья, подпишитесь на наш канал YouTube, чтобы получать видеоуроки.

19 мыслей на тему "Загрузка файлов методом перетаскивания с использованием JavaScript и PHP"

Еще одно небольшое обновление от меня: при изменении HTML-кода вы также сможете загрузить несколько файлов с помощью кнопки выбора файла:

Спасибо за это. Это работает хорошо. Мой запрос заключается в том, что фотография появляется в полном размере на html-странице. Как мне контролировать размер (мне нужен половинный размер)?

Добавить ширину и высоту в тег img.

Извините за многословие, но где тег изображения?

Проверьте строку ниже в custom.js

Спасибо за это. У меня загрузка работает. Сейчас я борюсь с тем, как обновить элемент управления загрузкой только что загруженного изображения. Есть предложения?

Я обновил статью и добавил ответы на ваш вопрос.

Спасибо!
Искал простой и работающий пример... Это был правильный!
Отличная работа!

Это отличный пост. Это действительно полезно для моих бизнес-сайтов.

я хочу сохранить данные до отправки идеи??

отличная работа: спасибо!
У меня он работает локально с xampp после установки chmod.

Я также хотел бы вставить данные в базу данных (через ajax.php), но я не могу заставить div отправлять больше данных (например, из переключателей).
Есть идеи?

Вы должны добавить свои данные в переменную form_data.

Всем привет,
в моем случае мне пришлось удалить теги javascript, чтобы он работал…

хороший пример.
У меня есть еще один пример Drag and Drop File Uploader при работе с HTML, Bootstrap.

Привет, мне нужно передать в «ajax.php» другие значения (например, форму с сообщением).
Как я могу изменить JS, чтобы получить его?
Спасибо

в HTML
изменить
———————————
функция upload_file(e) e.preventDefault();
fileobj = e.dataTransfer.files[0];
ajax_file_upload(fileobj);
>
———————————

Работает как шарм

выглядит многообещающе, но указателя на файлы нет, а КОПИРОВАТЬ в буфер обмена не работает,
и когда вы выбираете код, он включает номера строк, которые нужно отредактировать.

Спасибо за этот пример. Действительно полезно для меня. Один быстрый вопрос.

Как мы можем сделать так, чтобы он загружался по нажатию кнопки, а не автоматически?

Читайте также: