Я изо всех сил пытаюсь найти документацию или примеры реализации индикатора выполнения загрузки с помощью fetch .
Это единственная ссылка, которую я нашел до сих пор , в которой говорится:
События выполнения - это функция высокого уровня, которая пока не поступает в выборку. Вы можете создать свой собственный, просмотрев
Content-Length
заголовок и используя сквозной поток для отслеживания полученных байтов.Это означает, что вы можете явно обрабатывать ответы без какого-либо
Content-Length
другого. И, конечно, даже еслиContent-Length
это так, это может быть ложь. С помощью потоков вы можете справиться с этой ложью, как хотите.
Как мне написать «сквозной поток для отслеживания отправленных байтов»? Если это имеет какое-то значение, я пытаюсь сделать это для загрузки изображений из браузера в Cloudinary .
ПРИМЕЧАНИЕ : меня не интересует библиотека Cloudinary JS , поскольку она зависит от jQuery, а мое приложение - нет. Меня интересует только потоковая обработка, необходимая для этого с помощью собственного javascript и fetch
полифилла Github .
источник
Ответы:
Потоки начинают появляться на веб-платформе ( https://jakearchibald.com/2016/streams-ftw/ ), но это еще только начало.
Вскоре вы сможете предоставить поток в качестве тела запроса, но открытый вопрос заключается в том, связано ли потребление этого потока с загруженными байтами.
Конкретные перенаправления могут привести к повторной передаче данных в новое место, но потоки не могут «перезапускаться». Мы можем исправить это, превратив тело в обратный вызов, который можно вызывать несколько раз, но мы должны быть уверены, что раскрытие количества перенаправлений не является утечкой безопасности, поскольку это будет первый раз, когда на платформе JS может обнаружить это.
Некоторые задаются вопросом, есть ли вообще смысл связывать потребление потока с загруженными байтами.
Короче говоря: это пока невозможно, но в будущем это будет обрабатываться либо потоками, либо переданным обратным вызовом более высокого уровня
fetch()
.источник
Мое решение - использовать axios , которая хорошо это поддерживает:
axios.request( { method: "post", url: "/aaa", data: myData, onUploadProgress: (p) => { console.log(p); //this.setState({ //fileprogress: p.loaded / p.total //}) } }).then (data => { //this.setState({ //fileprogress: 1.0, //}) })
У меня есть пример использования этого в реакции на github.
источник
axios
пользаfetch
илиXMLHttpRequest
под капотом?axios
что не используетсяfetch
под капотом и не имеет такой поддержки. Буквально сейчас для них пишу .Я не думаю, что это возможно. В проекте говорится:
(старый ответ):
Первый пример в главе о Fetch API дает некоторое представление о том, как:
Помимо использования
Promise
конструктора antipattern , вы можете видеть, чтоresponse.body
это Stream, из которого вы можете читать побайтово с помощью Reader, и вы можете запускать событие или делать что угодно (например, регистрировать прогресс) для каждого из них.Однако спецификация Streams , похоже, не совсем закончена, и я понятия не имею, работает ли это уже в какой-либо реализации выборки.
источник
fetch
. Меня интересуют индикаторы прогресса загрузки файла.Promise
конструктор не нужен.Response.body.getReader()
возвращаетPromise
. См. Раздел Как устранить ошибку Uncaught RangeError при загрузке json большого размераgetReader
не возвращает обещание. Понятия не имею, какое это имеет отношение к сообщению, на которое вы ссылаетесь..getReader()
,.read()
метод возвращаетPromise
. Это то, что пытался передать. Ссылка намекает на предпосылку, что если можно проверить прогресс для загрузки, то можно проверить и для загрузки. Составьте шаблон, который в значительной степени возвращает ожидаемый результат; это прогресс дляfetch()
загрузки. Не нашли способ или объект в jsfiddle, вероятно , отсутствует что - то простое. Очень быстрое тестирование при загрузке файла без имитации условий сети; хотя только что вспомнил .echo
Blob
File
localhost
Network throttling
Обновление: как говорится в принятом ответе, сейчас это невозможно. но приведенный ниже код некоторое время решал нашу проблему. Должен добавить, что, по крайней мере, нам пришлось перейти на использование библиотеки, основанной на XMLHttpRequest.
const response = await fetch(url); const total = Number(response.headers.get('content-length')); const reader = response.body.getReader(); let bytesReceived = 0; while (true) { const result = await reader.read(); if (result.done) { console.log('Fetch complete'); break; } bytesReceived += result.value.length; console.log('Received', bytesReceived, 'bytes of data so far'); }
благодаря этой ссылке: https://jakearchibald.com/2016/streams-ftw/
источник
content-length
! == длина тела. Когда используется сжатие http (обычно для больших загрузок), длина содержимого - это размер после сжатия http, а длина - это размер после извлечения файла.bytesReceived
становится больше, чемtotal
Поскольку ни один из ответов не решает проблему.
Просто ради реализации вы можете определить скорость загрузки с помощью некоторого небольшого начального фрагмента известного размера, а время загрузки можно рассчитать с помощью длины содержимого / скорости загрузки. Вы можете использовать это время как оценку.
источник
Возможный обходной путь - использовать
new Request()
конструктор, а затем проверитьRequest.bodyUsed
Boolean
атрибутчтобы определить, является ли поток
distributed
Вернуть
fetch()
Promise
изнутри.then()
цепочку к рекурсивному.read()
вызову,ReadableStream
когдаRequest.bodyUsed
равноtrue
.Обратите внимание, что этот подход не считывает байты,
Request.body
поскольку байты передаются в конечную точку. Кроме того, загрузка может завершиться задолго до того, как какой-либо ответ будет полностью возвращен браузеру.const [input, progress, label] = [ document.querySelector("input") , document.querySelector("progress") , document.querySelector("label") ]; const url = "/path/to/server/"; input.onmousedown = () => { label.innerHTML = ""; progress.value = "0" }; input.onchange = (event) => { const file = event.target.files[0]; const filename = file.name; progress.max = file.size; const request = new Request(url, { method: "POST", body: file, cache: "no-store" }); const upload = settings => fetch(settings); const uploadProgress = new ReadableStream({ start(controller) { console.log("starting upload, request.bodyUsed:", request.bodyUsed); controller.enqueue(request.bodyUsed); }, pull(controller) { if (request.bodyUsed) { controller.close(); } controller.enqueue(request.bodyUsed); console.log("pull, request.bodyUsed:", request.bodyUsed); }, cancel(reason) { console.log(reason); } }); const [fileUpload, reader] = [ upload(request) .catch(e => { reader.cancel(); throw e }) , uploadProgress.getReader() ]; const processUploadRequest = ({value, done}) => { if (value || done) { console.log("upload complete, request.bodyUsed:", request.bodyUsed); // set `progress.value` to `progress.max` here // if not awaiting server response // progress.value = progress.max; return reader.closed.then(() => fileUpload); } console.log("upload progress:", value); progress.value = +progress.value + 1; return reader.read().then(result => processUploadRequest(result)); }; reader.read().then(({value, done}) => processUploadRequest({value,done})) .then(response => response.text()) .then(text => { console.log("response:", text); progress.value = progress.max; input.value = ""; }) .catch(err => console.log("upload error:", err)); }
источник
const req = await fetch('./foo.json'); const total = Number(req.headers.get('content-length')); let loaded = 0; for await(const {length} of req.body.getReader()) { loaded = += length; const progress = ((loaded / total) * 100).toFixed(2); // toFixed(2) means two digits after floating point console.log(`${progress}%`); // or yourDiv.textContent = `${progress}%`; }
источник
Ключевой частью является ReadableStream ≪ obj_response .body≫.
Образец:
let parse=_/*result*/=>{ console.log(_) //... return /*cont?*/_.value?true:false } fetch(''). then(_=>( a/*!*/=_.body.getReader(), b/*!*/=z=>a.read().then(parse).then(_=>(_?b:z=>z)()), b() ))
Вы можете протестировать его запуск на огромной странице, например, https://html.spec.whatwg.org/ и https://html.spec.whatwg.org/print.pdf . CtrlShiftJ и загрузите код в.
(Проверено в Chrome.)
источник