Индикатор хода загрузки файла с Axios и VueJS

Создание компонента Vue

Сначала создадим наш компонент Vue. Для этого создадим новый файл FileProgress.vue со следующим содержанием:

<template>
</template>
<script>
  export default {
  }
</script>

Вы можете самостоятельно добавить тег style для стилей, если захотите (рекомендуется, для кода в продакшине, что бы приложение выглядело хорошо), но сейчас мы сделаем его максимально простым. Далее определим наш шаблон компонента.

Шаблон компонента

Теперь нам нужно добавить наш шаблон, поэтому добавим следующее в тег template:

<template>
  <div class="container">
    <div class="large-12 medium-12 small-12 cell">
      <label>File
        <input type="file" id="file" ref="file" v-on:change="handleFileUpload()"/>
      </label>
      <br>
      <progress max="100" :value.prop="uploadPercentage"></progress>
      <br>
      <button v-on:click="submitFile()">Submit</button>
    </div>
  </div>
</template>

Есть пара вещей, на которые стоит обратить внимание. Наш input имеет атрибут ref=»file». Это позволяет сделать input доступным через локальную переменную $refs в нашем компоненте. Далее мы ожидаем, когда пользователь начнет загружать файл. В этот момент, мы копируем выбранный файл в локальную переменную file (которую мы добавим на следующем шаге), чтобы мы могли отправить его на сервер.

Самым важным элементом шаблона является элемент <progress>. Через него мы семантически отобразим ход загрузки файлов. Есть пара атрибутов, которые указывают на элемент. Первым является атрибут max. Мы установили его на 100, так как мы будем вычислять процент на основе 100.

Следующий атрибут в элементе <progress> — это атрибут :value.prop=»uploadPercentage». Поскольку элемент <progress> не является input, его значение является атрибутом, а не фактическим значением, которое имеет элемент input. Мы привязываем значение value в виде prop (с :value.prop) к вычисленному uploadPercentage. На следующем шаге мы добавим данные для uploadPercentage.

Последнее замечание о шаблоне — кнопка «Submit», при нажатии на которую запускается метод submitFile(). Это метод просто отправляет файл на сервер.

Добавим переменные в data

Добавим необходимые переменные используемые компонентом в метод data() компонента. Для этого добавим в свой компонент следующее:

data(){
  return {
    file: '',
    uploadPercentage: 0
  }
},

Переменная file используется для хранения файла, загруженного пользователем. Параметр uploadPercentage по умолчанию равен 0 и будет заполнен процентом, загруженным через Axios.

Метод handleFileUpload()

Этот метод вызывается всякий раз, когда пользователь выбирает файл для загрузки. Просто добавьте это к объекту methods:

handleFileUpload(){
  this.file = this.$refs.file.files[0];
}

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

Метод submitFile()

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

submitFile(){
  let formData = new FormData();
  formData.append('file', this.file);
  axios.post( '/file-progress',
    formData,
    {
      headers: {
          'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: function(progressEvent) {
        this.uploadPercentage = parseInt(Math.round(( progressEvent.loaded / progressEvent.total) * 100);
      }.bind(this)
    }
  ).then(function(){
    console.log('SUCCESS!!');
  })
  .catch(function(){
    console.log('FAILURE!!');
  });
},

Сначала мы инициализируем экземпляр объекта FormData():

let formData = new FormData();

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

formData.append('file', this.file);

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

Следующий код загружает файл на сервер:

axios.post( '/file-progress',
  formData,
  {
    headers: {
        'Content-Type': 'multipart/form-data'
    },
    onUploadProgress: function(progressEvent) {
      this.uploadPercentage = parseInt(Math.round(( progressEvent.loaded / progressEvent.total) * 100);
    }.bind(this)
  }
).then(function(){
  console.log('SUCCESS!!');
})
.catch(function(){
  console.log('FAILURE!!');
});

Мы отправляем данные в конечную точку /file-progress. Затем мы передаем formData в качестве второго параметра, который является параметром данных. Третий параметр — это наша конфигурация. Здесь мы добавляем наш заголовок для ‘Content-Type’: ‘multipart/form-data’, чтобы сервер знал, что мы можем прикрепить файлы.

Затем мы добавляем метод, который присоединяется к событию onUploadProgress. Вложенный метод содержит progressEvent в качестве параметра. Мы можем использовать этот параметр, чтобы определить, как далеко мы продвинулись в загрузке файлов. Во-первых, мы должны связать this с методом, чтобы иметь доступ к локальным переменным нашего компонента. Затем мы вычисляем процент загрузки, беря то, что было загружено, умножая его на 100, чтобы адаптировать его в процентный формат, а затем делим его на общее количество файлов для загрузки, чтобы получить процент:

this.uploadPercentage = parseInt( Math.round( ( progressEvent.loaded / progressEvent.total ) * 100 );

Так как мы передали его в uploadPercentage, VueJS установит наш индикатор выполнения для представления статуса. Это все, что нам действительно нужно, чтобы показать прогресс! Конечно, вы можете использовать и другие элементы и использовать вычисленный процент, чтобы показать отображение, но элемент <progress> является семантическим и может быть стилизован под ваши нужды.

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

Заключение

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


Источник

ТЕГИ:

Вы можете поделиться этой статьей в любой из соцсетей, представленных ниже:


Чтобы добавить свой комментарий, необходимо пройти аутентификацию
Комментарии
Ничего не найдено.