Estou lutando para encontrar documentação ou exemplos de implementação de um indicador de progresso de upload usando fetch .
Esta é a única referência que encontrei até agora , que afirma:
Os eventos de progresso são um recurso de alto nível que não chegará em busca por enquanto. Você pode criar o seu próprio olhando para o
Content-Length
cabeçalho e usando um fluxo de passagem para monitorar os bytes recebidos.Isso significa que você pode lidar explicitamente com as respostas, sem ser
Content-Length
diferente. E, claro, mesmo seContent-Length
estiver lá, pode ser mentira. Com os streams, você pode lidar com essas mentiras da maneira que quiser.
Como eu escreveria "um fluxo de passagem para monitorar os bytes" enviados? Se fizer alguma diferença, estou tentando fazer isso para fazer uploads de imagens do navegador para Cloudinary .
NOTA : Eu estou não interessados na biblioteca Cloudinary JS , uma vez que depende jQuery e meu aplicativo não. Estou interessado apenas no processamento de stream necessário para fazer isso com javascript nativo e fetch
polyfill do Github .
fonte
Respostas:
Os fluxos estão começando a chegar à plataforma da web ( https://jakearchibald.com/2016/streams-ftw/ ), mas ainda é cedo.
Em breve, você poderá fornecer um fluxo como o corpo de uma solicitação, mas a questão em aberto é se o consumo desse fluxo está relacionado aos bytes carregados.
Redirecionamentos específicos podem resultar na retransmissão de dados para o novo local, mas os fluxos não podem "reiniciar". Podemos corrigir isso transformando o corpo em um retorno de chamada que pode ser chamado várias vezes, mas precisamos ter certeza de que expor o número de redirecionamentos não é um vazamento de segurança, já que seria a primeira vez na plataforma JS poderia detectar isso.
Alguns estão questionando se faz sentido vincular o consumo de stream aos bytes carregados.
Resumindo: isso ainda não é possível, mas no futuro isso será tratado por streams ou algum tipo de retorno de chamada de nível superior transmitido
fetch()
.fonte
Minha solução é usar axios , que suporta isso muito bem:
Eu tenho um exemplo para usar isso no react no github.
fonte
axios
usofetch
ouXMLHttpRequest
sob o capô?axios
não usafetch
sob o capô e não tem tal suporte. Estou literalmente escrevendo agora para eles.Não acho que seja possível. O rascunho declara:
(resposta antiga):
O primeiro exemplo no capítulo Fetch API dá algumas dicas sobre como:
Além do uso do
Promise
antipadrão de construtor , você pode ver queresponse.body
é um Stream do qual você pode ler byte por byte usando um Reader e pode disparar um evento ou fazer o que quiser (por exemplo, registrar o progresso) para cada um deles.No entanto, a especificação do Streams não parece estar totalmente concluída e não tenho ideia se isso já funciona em qualquer implementação de busca.
fonte
fetch
. Estou interessado em indicadores de progresso para enviar um arquivo.Promise
construtor não é necessário.Response.body.getReader()
retorna aPromise
. Consulte Como resolver ogetReader
não retorna uma promessa. Não tenho ideia do que isso tem a ver com a postagem que você vinculou..getReader()
. O.read()
método retorna aPromise
. Isso é o que estava tentando transmitir. O link é uma alusão à premissa de que se o progresso pode ser verificado para download, o progresso pode ser verificado para upload. Monte um padrão que retorne o resultado esperado, em um grau apreciável; isso é progresso parafetch()
upload. Não encontrei um caminho paraecho
um objetoBlob
ouFile
em jsfiddle, provavelmente faltando algo simples. Testarlocalhost
arquivos de uploads muito rapidamente, sem imitar as condições da rede; embora apenas lembradoNetwork throttling
.Atualização: como diz a resposta aceita, é impossível agora. mas o código abaixo tratou do nosso problema por algum tempo. Devo acrescentar que pelo menos tivemos que passar a usar uma biblioteca baseada em XMLHttpRequest.
graças a este link: https://jakearchibald.com/2016/streams-ftw/
fonte
content-length
! == comprimento do corpo. Quando a compactação http é usada (comum para downloads grandes), o comprimento do conteúdo é o tamanho após a compactação http, enquanto o comprimento é o tamanho após a extração do arquivo.Uma vez que nenhuma das respostas resolve o problema.
Apenas para fins de implementação, você pode detectar a velocidade de upload com um pequeno pedaço inicial de tamanho conhecido e o tempo de upload pode ser calculado com content-length / upload-speed. Você pode usar este tempo como estimativa.
fonte
Uma possível solução alternativa seria utilizar o
new Request()
construtor e verificar oRequest.bodyUsed
Boolean
atributopara determinar se o fluxo é
distributed
Retorne a chamada recursiva
fetch()
Promise
de dentro.then()
encadeada para quando for igual a ..read()
ReadableStream
Request.bodyUsed
true
Observe que a abordagem não lê os bytes do
Request.body
conforme os bytes são transmitidos para o terminal. Além disso, o upload pode ser concluído muito antes de qualquer resposta ser retornada por completo ao navegador.fonte
fonte
A parte principal é ReadableStream ≪ obj_response .body≫.
Amostra:
Você pode testar sua execução em uma página enorme, por exemplo, https://html.spec.whatwg.org/ e https://html.spec.whatwg.org/print.pdf . CtrlShiftJ e carregue o código em.
(Testado no Chrome.)
fonte