Загрузка файлов с мониторингом выполнения в VanillaJS, Angular и VueJS

Когда я только начинал свой путь программирования, я прочитал книгу под названием «Head First - PHP & MySQL». Эта книга во многом изменила мое мнение и мою жизнь.

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

Но хотелось большего. Я выучил PHP, но мне хотелось немного больше асинхронности. Хотел бы я делать то, что делал PHP, но без того обновления, которое меня всегда беспокоило.

Через некоторое время я смог изучить JavaScript с помощью AJAX, так что я уже был близок к тому, что мне не хватало только асинхронной загрузки.

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

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

Шаг 1. Наш бэкэнд

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

Если вы хотите узнать больше о .NET Core, перейдите по этой ссылке https://docs.microsoft.com/pt-br/dotnet/core/

Но не стесняйтесь использовать бэкэнд-язык, который вам больше нравится. Как Node, PHP, Elixir и т. Д.

Шаг 2: понимание FormData

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

Этот интерфейс отлично подходит для использования с формами и необходим для отправки файла на сервер, поскольку он кодирует данные с использованием multipart / form-data, который является enctype для отправки файлов на сервер.

С помощью объекта FormData помимо буквальных значений мы можем добавить Blob и файлы с помощью метода append ().

См. Этот пример из сети разработчиков Mozilla:

var formData = new FormData();

formData.append("username", "Groucho");
formData.append("accountnum", 123456); // number 123456 is immediately converted to a string "123456"

// HTML file input, chosen by user
formData.append("userfile", fileInputElement.files[0]);

// JavaScript file-like object
var content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var blob = new Blob([content], { type: "text/xml"});

formData.append("webmasterfile", blob);

var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php");
request.send(formData);

Это мы и будем использовать здесь.

Шаг 3. Загрузим файл

Пора. Загрузим файл.

3.1 С VanillaJS

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

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

Заголовок и абзац показывают ход и результат текста. Проверить код:

В нашем примере мы будем использовать XMLHttpRequest, который используется для взаимодействия с серверами. Благодаря этому мы можем обновлять фрагменты нашей страницы без обновления страниц. XMLHttpRequest широко используется в программировании AJAX.

Объекты XMLHttpRequest имеют свойство upload, которое возвращает объект XMLHttpRequestUpload, за которым можно наблюдать для отслеживания хода загрузки. Кроме того, этот объект позволяет прикреплять события для отслеживания прогресса.

Эти события:

  1. loadstart - загрузка началась
  2. прогресс - периодически доставляется, чтобы указать на достигнутый прогресс.
  3. abort - операция загрузки прервана.
  4. ошибка - загрузка не удалась из-за ошибки.
  5. load - загрузка успешно завершена.
  6. timeout - время загрузки истекло, поскольку ответ не пришел в течение интервала времени, указанного в XMLHttpRequest.timeout.
  7. loadend - загрузка завершена. Это событие не делает различий между успехом или неудачей и отправляется в конце загрузки независимо от результата. Перед этим событием уже было доставлено одно из load, error, abort или timeout, чтобы указать почему закачка закончилась.

Наш код JavaScript для загрузки показан ниже:

ПРИМЕЧАНИЕ. Этот код был адаптирован из https://codepen.io/PerfectIsShit/pen/zogMXP

Как вы видели, мы прикрепили некоторые события. Один в XMLHttpRequestUpload, это прогресс, и мы добавили в XMLHttpRequest следующие события: load, error и abort.

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

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

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

var percent = Math.round((event.loaded / event.total) * 100);

Когда загрузка завершается, запускается событие load и выполняется функция completeHandler, которая показывает responseText, пришедший с сервера, и устанавливает нулевое значение хода выполнения.

Если у нас есть ошибка. Будет запущено событие error и будет выполнен errorHandler, и нечто подобное произойдет с событием отмены.

Итак, это наш пример загрузки с использованием Vanilla JS. Этот пример важен и упрощает понимание следующих примеров.

3.2 С VueJS

Теперь мы разработаем наш пример загрузки с помощью Vue. Отличный JavaScript-фреймворк.

Для разработки нашего примера мы будем использовать форму, подобную той, которая уже представлена ​​здесь в примере Vanilla JS, но с некоторыми изменениями, потому что некоторые вещи во Vue проще.

А для отправки нашего запроса мы будем использовать Axios, который является http-клиентом на основе Promises, а в Vue он отлично подходит для обработки HTTP-запросов.

Чтобы узнать, как добавить axios в ваш проект Vue, перейдите по этой ссылке https://www.npmjs.com/package/vue-axios

Итак, в нашем файле Home.vue у нас есть следующий код:

Сначала посмотрим на нашу форму. Обратите внимание, что мы используем ref, чтобы получить элемент в скрипте, и в форме мы прикрепили событие отправки с помощью @submit.

В нашем JavaScript есть свойства status и progressText, а также метод под названием sendFile.

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

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

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

Наконец, мы прикрепляем .then () к Promise, чтобы получить окончательный результат запроса. Если вы хотите обнаруживать ошибки, когда они возникают, вы можете прикрепить. catch () к Promise.

3.1 С Angular

Теперь мы здесь. Давайте сделаем это с помощью Angular. Angular - прекрасный фреймворк для разработки веб-приложений, который поддерживается Google и поддерживает (возможно, родной) язык Microsoft под названием TypeScript.

Angular - это фреймворк или лучше, платформа, и, в отличие от Vue, в Angular вещи немного более связаны в том смысле, что основные инструменты для разработки уже присутствуют. Инструменты для проверки формы, HTTP-запросов и т. Д.

Так что здесь нам не нужно будет добавлять еще один инструмент, как мы это делали во Vue при добавлении axios. Здесь мы используем модуль HttpClienteModule из @ angular / common / http.

В нашем проекте angular у нас есть простой компонент, вызывающий home, и, опять же, наша форма такая же, но с использованием возможностей Angular. См. Наш файл home.component.html ниже:

У нас есть событие отправки, прикрепленное к нашей форме, которое вызывает метод sendFile, и у нас есть некоторая ссылочная переменная шаблона, такая как refs в Vue. В Angular вам нужно определить с помощью решетки (#).

У нас есть ссылки #progressBar и #inputFile, а также два свойства: status и progressText.

Итак, давайте посмотрим на наш машинописный файл:

Сначала посмотрите на использование @ViewChild. Этот декор используется для запроса элементов в HTML.

Съел конструктор, который мы вводили HttpClient для использования внутри метода sendFile. В этом методе мы получаем файл и помещаем в него объект FormData (здесь то же самое).

После этого мы выполняем вызов POST, отправляя объект FormData. Обратите внимание на использование параметров в методе .post (), где мы передали два атрибута: наблюдать и reportProgress со значениями events и true соответственно.

Определяя наблюдение как события, мы сообщаем http-клиенту, что хотим получать события, которые происходят в нашем запросе. А определение resportProgress как true позволяет нам отслеживать события загрузки.

Теперь, когда мы уже знаем, как это работает, давайте посмотрим на подписку. . post () возвращает Observable, и при подписке мы можем получить текущее событие.

Поэтому мы использовали инструкцию switch, чтобы проверить тип события и что-то с этим сделать. Мы используем два события: HttpEventType.UploadProgress и HttpEventType.Response. Они предназначены для мониторинга загрузки и финала. ответ соответственно.

Итак, событие UploadProgress имеет те же замечательные свойства, которые уже представлены здесь: загружено и всего. Как вы можете подумать, вычисления производятся одинаково во Vue и VanillaJS.

Итак, при каждом событии загрузки мы меняем progressText и значение HTML-элемента progress.

Наконец, в событии Response мы получаем event.body, полученный от API, и устанавливаем статус для отображения в шаблоне HTML.

АГА!! Мы закончили ... Но подождите, а как насчет ReactJS? Так что я не разработчик React, но думаю, что с React вам следует использовать стороннюю библиотеку, чтобы обрабатывать http-запросы, например axios. Так что у нас это уже есть. Если вы хотите использовать собственный XMLHttpRequest, у нас также есть это.

Так что, если вы разработчик React, просто сделайте это и поделитесь с нами. Спасибо!!

Резюме

Эй, мы сделали это. Теперь у нас есть демонстрация загрузки тремя способами. В Vue, Vanilla и Angular используются разные формы с XMLHttpRequest, Axios и HttpModule в Angular.

Этот пример очень обычный, простой и очень полезный для изучения HTTP-запросов с помощью JavaScript / TypeScript. Если это служит упражнением, возьмите этот пример и примените его к существующему проекту или просто добавьте больше красоты / функциональности в наш пример (который довольно сырой).

Наконец, вы можете получить все коды для этого сообщения, WebAPI, Vanillar, Angular и Vue, перейдя по ссылке https://github.com/geeksilva97/Medium/tree/master/uploading

Чтобы увидеть, как это работает, посетите мой веб-сайт по адресу https://codesilva.github.io/demos/medium/uploading.

Это все. Увидимся!

Перекрытия