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

<template>

</template>

<script>
  export default {

  }
</script>

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

Добавить код шаблона

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

<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>

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

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

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

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

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

Добавить данные в скрипт

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

/*
  Defines the data used by the component
*/
data(){
  return {
    file: '',
    uploadPercentage: 0
  }
},

The file data will be used to store the file uploaded by the user. The uploadPercentage is defaulted to 0 and will be filled with the percentage uploaded through Axios.

Добавить метод handleFileUpload()

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

/*
  Handles a change on the file upload
*/
handleFileUpload(){
  this.file = this.$refs.file.files[0];
}

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

Добавить метод submitFile()

Этот метод содержит ядро ​​нашего функционала. Это должно выглядеть так:

/*
  Submits the file to the server
*/
submitFile(){
  /*
    Initialize the form data
  */
  let formData = new FormData();

  /*
    Add the form data we need to submit
  */
  formData.append('file', this.file);

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

Во-первых, мы инициализируем экземпляр объекта FormData():

/*
  Initialize the form data
*/
let formData = new FormData();

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

/*
  Add the form data we need to submit
*/
formData.append('file', this.file);

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

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

/*
  Make the request to the POST /single-file URL
*/
axios.post( '/file-progress',
  formData,
  {
    headers: {
        'Content-Type': 'multipart/form-data'
    },
    onUploadProgress: function( progressEvent ) {
      this.uploadPercentage = parseInt( Math.round( ( progressEvent.loaded * 100 ) / progressEvent.total ) );
    }.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 * 100 ) / progressEvent.total ) );

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

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

Вывод

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

Если у вас есть какие-либо вопросы, не стесняйтесь связаться или оставить комментарий ниже!