XMLHttpRequest и возобновляемая закачка

XMLHttpRequest и возобновляемая закачка

Здравствуйте! В этой статье я  хочу рассказать о так называемой возобновляемой закачке во время запроса файла методом XMLHttpRequest.  Ведь он  даёт возможность загружать файл как угодно: во множество потоков, с догрузкой  и прочими вариантами.

XMLHttpRequest и возобновляемая закачка

Тут же мы рассмотрим подход к организации загрузки.

Неточный upload.onprogress

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

Есть же  такой xhr.upload.onprogress – вешаем  на него обработчик, по свойству loaded события onprogress  и смотрим, сколько байт загрузилось. А при обрыве –  просто возобновляем загрузку с последнего байта.

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

Вот так:

var slice = file.slice(10, 100); 
// прочитать байты с 10-го по 99-й включительно 
xhr.send(slice); // ... и отправить эти байты в запросе.

Но так не получится!
Всё дело в том, что  событие upload.onprogress срабатывает, когда байты отправлены, но были ли они получены сервером – это уже  другой вопрос и  браузер этого не знает. Может, их прокси-сервер закешировал, может серверный процесс «завис» в процессе обработки, да мало ли еще чего могло произойти.

Поэтому onprogress годится лишь для индикации прогресса загрузки.

А вот для загрузки нам нужно точно знать количество загруженных байт.  Это может  знать только сервер.

Алгоритм возобновляемой загрузки

За загрузку  файла будет  отвечать объект Uploader,  вот его общий вид:

function Uploader(file, onSuccess, onFail, onProgress) { 
var fileId = file.name + '-' + file.size + '-' + +file.lastModifiedDate; 
var errorCount = 0; 
var MAX_ERROR_COUNT = 6; 
function upload() { ... } 
function pause() { ... } this.upload = upload; this.pause = pause; }
  • Аргументы для new Uploader:
file
Объект File API. Может быть получен из формы, либо как результат Drag’n’Drop.
onSuccess, onFail, onProgress
Читайте также  Метод fetch как замена XMLHttpRequest

Функции-обработчики, которые будут вызываться в процессе (onProgress) и при окончании загрузки.

  • Подробнее про важные данные, с которыми мы будем работать в процессе загрузки:
fileId
Уникальный идентификатор файла, генерируется по имени, размеру и дате модификации. По нему мы всегда сможем возобновить загрузку, в том числе и после закрытия и открытия браузера.
startByte
С какого байта загружать.  По умолчанию – с нулевого.
errorCount / MAX_ERROR_COUNT
Текущее число ошибок / максимальное число ошибок подряд, после которого загрузка считается неудавшейся.

Алгоритм загрузки:

  1. Генерируем fileId из названия, размера, даты модификации файла.
  2. Спрашиваем сервер, есть ли уже такой файл, и если да – сколько байт уже загружено?
  3. Отсылаем файл с позиции, которую сказал сервер.

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

Итого

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

Его можно усложнить:

  • добавить подсчёт контрольных сумм и проверку целостности пересылаемых файлов,
  • для индикации прогресса вместо неточного xhr.upload.onprogress – сделать дополнительный запрос к серверу, в который и отдавать текущий прогресс.
  • разбивать файл на части и грузить в несколько потоков, несколькими параллельными запросами в асинхронном режиме.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Поделиться

Об авторе

admin administrator

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: