Почему при загрузке XMLHttpRequest в Firefox происходит сбой? - PullRequest
0 голосов
/ 29 июня 2018

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

Проблема возникает, когда сервер прекращает обработку загрузки до ее завершения (например, закрытие соединения с ошибкой 413 Payload Too Large, если загружаемые файлы слишком велики). Если такая ошибка возникает при использовании Safari или Chrome, они прекратят загрузку, как я собираюсь.

Однако в Firefox он, похоже, игнорирует это и повторяет загрузку несколько раз перед остановкой.

Мой код выглядит следующим образом:

// Initialize a new request object.
let req = new XMLHttpRequest();

// Set expected response as JSON.
req.responseType = 'json';

// Set event handlers.
req.upload.onreadystatechange = function(e) { console.log(e.type); }
req.upload.onuploadstart = function(e) { console.log(e.type); }
req.upload.onprogress = function(e) { console.log(e.type); }
req.upload.onabort = function(e) { console.log(e.type); }
req.upload.onload = function(e) { console.log(e.type); }
req.upload.ontimeout = function(e) { console.log(e.type); }
req.upload.onuploadend = function(e) { console.log(e.type); }

// Open request, set request header.
req.open('POST', '/some-endpoint', true);
req.setRequestHeader('Content-type', 'multipart/form-data;boundary=---some-boundary---');

// Create FormData object to submit.
let fd = new FormData(formElement);

// Send data.
req.send(fd);

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

loadstart
progress (multiple)
Failed to load resource (413 Request Entity Too Large)

как я и ожидал. В Firefox события запускаются в следующем порядке:

loadstart
progress (multiple, ignoring connection closes and restarting upload multiple times)
loadend

Firefox, похоже, не запускает событие load, error, abort или timeout до события loadend, как указано в документации XMLHttpRequest.upload

Просмотр сетевых вкладок каждого из инструментов разработчика браузеров показывает, что Chrome и Safari оба распознают, что сервер ответил 413, но Firefox не распознал никакого статуса ответа (даже после loadend).

Версии Firefox Quantum 62.0b3 (64-разрядная версия). Safari - это 11.0.1. Хром 67.0.3396.99.

Итак, вопрос: Почему Firefox не может распознать, что произошла ошибка сервера во время загрузки, и отменить загрузку, где Safari и Chrome могут? и Есть ли способ Я могу решить это?

1 Ответ

0 голосов
/ 29 июня 2018

Как и Коди Г. предположил это может быть ошибка или связана с ошибкой в ​​Firefox.

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

Firefox, Safari и Chrome - все события запуска в том же порядке, когда загрузка успешна (т.е. когда сервер не отправляет ответ или не закрывает соединение до завершения загрузки). Этот заказ:

readystatechange (readyState = 1)
loadstart
progress (1...n times)
load
loadend
readystatechange (readyState = 2)
readystatechange (readyState = 4)

... как и ожидалось.

Safari и Chrome запускают события в том же порядке, когда загрузка не удалась (т.е. когда сервер закрывает соединение и отправляет ответ). Этот заказ:

readystatechange (readyState = 1)
loadstart
progress (1...n times)
[the server responds with an error, which does *not* trigger an error event]
readystatechange (readyState = 2)
readystatechange (readyState = 3)
readystatechange (readyState = 4)

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

readystatechange (readyState = 1)
loadstart
progress (1...n times, including retrying from the start more than once when the server responds or closes the connection)
readystatechange (readyState = 2)
readystatechange (readyState = 3)
readystatechange (readyState = 4)
error
loadend

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

let prevLoaded = 0;
xhr.upload.addEventListener('progress', function(e) {
    if (prevLoaded !== 0 && e.loaded <= prevLoaded) {
        xhr.abort();
        return;
    }
    prevLoaded = e.loaded;
}, false);

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

readystatechange (readyState = 1)
loadstart
progress (1...n times, but almost always stopping after the server closes the connection or responds with an error)
readystatechange (readyState = 4)
abort
loadend
...