Dans l’exemple fournis j’utilise le premier cas. Pour le lancer il faut :
- Un petit serveur statique, exemple avec Python3 :
python3 -m http.server - Changer le lien dans le
fetch("URL TO DOWNLAOD HERE")avec le chemin vers fichier sur le serveur statique.
Ressources MDN :
On vient lire le corps de la réponse morceau par morceau. La taille des morceaux est définis par le navigateur.
Cette technique est composée d’une seule boucle sans gestion de mémoire ce qui lui assure une simplicité d’implémentation. Cependant le flux est directement consommé donc absolument pas générique.
let byteLength = 0
for await (const chunk of response.body) {
chunk.byteLength += chunk.byteLength
}On crée une nouvelle instance de TransformStream qui va visiter chaque morceau avant de les transmettre au reste de la chaîne via le contrôleur.
L’avantage du TransformStream ce qui permet de gagner en abstraction le flux n’est pas consommé donc le développeur peut continuer à chaîner pour finir par appeler la méthode pipeTo par exemple.
Une implémentation plus propre serait de créer une nouvelle sous-classe de TransformStream. Pour émettre des événements ou exiger une propriété avec une barre de progression, etc.
let byteLength = 0
response.body.pipeThrough(new TransformStream({
transform: (chunk, controller) => {
progress.value = chunk.byteLength
// Visit the chunck and pass to the next stream
controller.enqueue(chunk)
}
}))La méthode getReader peut aussi être utilisée pour avoir un meilleur contrôle de mémoire grâce à BYOB.
Avec ce dernier c’est au développeur d’apporter son propre tampon mémoire.
Donc on gagne en contrôle mémoire mais la simplicité en prend un coup.
On peut allouer directement un tampon qui va tout stocker et limiter son débit (ou pas). On peut aussi spécifier la taille des éléments avec les différents tableaux typés qui servent de vue sur le tampon. Mais je vais pas rentrer en détails sur ce genre de choses car très spécifique au besoin.
const reader = response.body.getReader({ mode: "byob" })
let byteLength = 0
// Allocate memory
let buffer = new ArrayBuffer(1024)
for (;;) {
const { done, value } = await reader.read(new Uint8Array(buffer));
if (done) {
break;
}
byteLength += value.byteLength;
// Buffer is detached
buffer = value.buffer
}