# Blob
`ArrayBuffer` et les vues font partie de la norme ECMA, une partie de JavaScript.
Dans le navigateur, il existe d'autres objets de niveau supérieur, décrits dans [File API](https://www.w3.org/TR/FileAPI/), en particulier `Blob`.
`Blob` consiste en une chaîne de caractères optionnelle `type` (un type de MIME habituellement), plus `blobParts` -- une séquence d'autres objets `Blob` , chaînes de caractères et `BufferSource`.

La syntaxe du constructeur est la suivante:
```js
new Blob(blobParts, options);
```
- **`blobParts`** est un tableau de `Blob`/`BufferSource`/`String`.
- **`options`** objet optionnel:
- **`type`** -- le type du `Blob`, généralement de type MIME, par exemple. `image/png`,
- **`endings`** -- s'il faut transformer la fin de ligne pour rendre le `Blob` correspondent aux nouvelles lignes de l'OS actuel (`\r\n` ou `\n`). `"transparent"` Par défaut (ne fait rien), mais peut aussi être `"native"` (transformer).
Par exemple:
```js
// créer un Blob à partir d'une chaîne
let blob = new Blob(["…"], {type: 'text/html'});
// veuillez noter: le premier argument doit être un tableau [...]
```
```js
// créer un objet blob à partir d'un tableau typés et de chaînes de caractères
let hello = new Uint8Array([72, 101, 108, 108, 111]); // "Hello" sous forme binaire
let blob = new Blob([hello, ' ', 'world'], {type: 'text/plain'});
```
Nous pouvons extraire des parties du `Blob` avec :
```js
blob.slice([byteStart], [byteEnd], [contentType]);
```
- **`byteStart`** -- l'octet de départ, par défaut 0.
- **`byteEnd`** -- le dernier octet (exclusif, par défaut jusqu'à la fin).
- **`contentType`** -- Le `type` du nouvel objet blob, par défaut le même que la source.
Les arguments sont similaires à `array.slice`, les nombres négatifs sont également autorisés.
```smart header="Les objets `Blob` sont immuables"
Nous ne pouvons pas modifier les données directement dans un `Blob`, mais nous pouvons découper des parties d'un `Blob`, créer de nouveaux objets `Blob` à partir d'eux, les mélanger dans un nouveau `Blob` et ainsi de suite.
Ce comportement est similaire aux chaînes de caractères JavaScript: nous ne pouvons pas changer un caractère dans une chaîne, mais nous pouvons créer une nouvelle chaîne corrigée.
```
## Blob comme URL
Un Blob peut être facilement utilisé comme URL pour ``, `
` ou d'autres balises, pour afficher son contenu.
Grâce au `type`, nous pouvons également télécharger / uploader des objets `Blob`, et le `type` devient naturellement `Content-Type` dans les requêtes réseau.
Commençons par un exemple simple. En cliquant sur un lien, vous téléchargez un `Blob` généré dynamiquement avec le contenu de `hello world` sous forme de fichier:
```html run
Download
```
On peut aussi créer un lien dynamiquement en JavaScript et simuler un clic par `link.click()`, puis le téléchargement démarre automatiquement.
Voici un code similaire qui oblige l'utilisateur à télécharger le `Blob` créé dynamiquement, sans aucun HTML :
```js run
let link = document.createElement('a');
link.download = 'hello.txt';
let blob = new Blob(['Hello, world!'], {type: 'text/plain'});
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);
```
`URL.createObjectURL` prend un `Blob` et crée une URL unique pour celui-ci, sous la forme `blob:/`.
Voilà à quoi ressemble la valeur de `link.href`:
```
blob:https://javascript.info/1e67e00e-860d-40a5-89ae-6ab0cbee6273
```
Pour chaque URL générée par `URL.createObjectURL`, le navigateur stocke en interne un mappage URL -> `Blob`. De telles URL sont donc courtes, mais permettent d'accéder au `Blob`.
Une URL générée (et donc le lien avec elle) n'est valide que dans le document actuel, tant qu'il est ouvert. Et cela permet de référencer le `Blob` dans `
`, ``, essentiellement tout autre objet qui attend une URL.
Une URL générée (et donc le lien avec elle) n'est valide que dans le document actuel, tant qu'il est ouvert. Et cela permet de référencer le `Blob` dans `
`,``, ou tout autre objet qui attend une URL.
Il y a cependant un effet secondaire. Bien qu'il y ait un mappage pour un `Blob`, le `Blob` lui-même réside dans la mémoire. Le navigateur ne peut pas le libérer.
Le mappage est automatiquement effacé lors du déchargement du document, les objets `Blob` sont alors libérés. Mais si une application dure longtemps, cela ne se produit pas de sitôt.
**Donc, si nous créons une URL, ce `Blob` restera en mémoire, même s'il n'est plus nécessaire.**
`URL.revokeObjectURL(url)` supprime la référence du mappage interne, permettant ainsi de supprimer le `Blob` (s'il n'y a pas d'autres références), et de libérer la mémoire.
Dans le dernier exemple, nous voulons que le `Blob` ne soit utilisé qu'une seule fois, pour un téléchargement instantané, donc nous appelons `URL.revokeObjectURL(link.href)` immédiatement.
Dans l'exemple précédent avec le lien HTML cliquable, nous n'appelons pas `URL.revokeObjectURL(link.href)`, car cela rendrait l'url `Blob` invalide. Après la révocation, comme le mappage est supprimé, l'URL ne fonctionne plus.
## Blob en base64
Une alternative à `URL.createObjectURL` est de convertir un `Blob` en une chaîne de caractères encodée en base64.
Cet encodage représente des données binaires sous la forme d'une chaîne de caractères "lisibles" ultra-sûrs avec des codes ASCII de 0 à 64. Et ce qui est plus important - nous pouvons utiliser cet encodage dans "data-urls".
Une [URL de données](mdn:/http/Data_URIs) a la forme `data:[][;base64],`. Nous pouvons utiliser de telles URL partout, au même titre que les URL "ordinaires".
Par exemple, voici un smiley:
```html
```
Le navigateur décodera la chaîne de caractères et affichera l'image:
Pour transformer un `Blob` en base64, nous utiliserons l'objet `FileReader` intégré. Il peut lire les données des Blobs dans plusieurs formats. Dans le [chapitre suivant](info:file) nous le couvrirons plus en détail.
Voici la démo du téléchargement d'un blob, maintenant via base-64:
```js run
let link = document.createElement('a');
link.download = 'hello.txt';
let blob = new Blob(['Hello, world!'], {type: 'text/plain'});
*!*
let reader = new FileReader();
reader.readAsDataURL(blob); // convertit le blob en base64 et appelle onload
*/!*
reader.onload = function() {
link.href = reader.result; // URL de données
link.click();
};
```
Les deux manières de créer une URL d'un `Blob` sont utilisables. Mais généralement `URL.createObjectURL(blob)` est plus simple et plus rapide.
```compare title-plus="URL.createObjectURL(blob)" title-minus="Blob vers l'URL de données"
+ Nous devons les révoquer si nous nous soucions de la mémoire.
+ Accès direct au blob, pas d'"encodage / décodage"
- Pas besoin de révoquer quoi que ce soit.
- Perte de performances et de mémoire sur les gros objets `Blob` pour l'encodage.
```
## Image à blob
Nous pouvons créer un `Blob` d'une image, une partie d'image, ou même faire une capture d'écran de page. C'est pratique pour le télécharger quelque part.
Les opérations sur les images se font via l'élément `