|
1 |
| -# Resumable file upload |
| 1 | +# Upload pouvant être repris |
2 | 2 |
|
3 |
| -With `fetch` method it's fairly easy to upload a file. |
| 3 | +Avec la méthode `fetch`, il est assez facile de upload un fichier. |
4 | 4 |
|
5 |
| -How to resume the upload after lost connection? There's no built-in option for that, but we have the pieces to implement it. |
| 5 | +Comment reprendre l'upload après une perte de connexion ? Il n'y a pas d'option intégrée pour cela, mais nous avons les pièces pour l'implémenter. |
6 | 6 |
|
7 |
| -Resumable uploads should come with upload progress indication, as we expect big files (if we may need to resume). So, as `fetch` doesn't allow to track upload progress, we'll use [XMLHttpRequest](info:xmlhttprequest). |
| 7 | +Les uploads pouvant être repris devraient être accompagnés d'une indication de progression, puisque nous pouvons nous attendre à de gros fichiers (au cas où on devrait reprendre). Donc, comme `fetch` ne permet pas de suivre la progression du téléchargement, nous utiliserons [XMLHttpRequest](info:xmlhttprequest). |
8 | 8 |
|
9 |
| -## Not-so-useful progress event |
| 9 | +## Événement de progression pas si utile |
10 | 10 |
|
11 |
| -To resume upload, we need to know how much was uploaded till the connection was lost. |
| 11 | +Pour reprendre l'upload, nous devons savoir combien a été uploadé jusqu'à ce que la connexion soit perdue. |
12 | 12 |
|
13 |
| -There's `xhr.upload.onprogress` to track upload progress. |
| 13 | +Il y a `xhr.upload.onprogress` pour suivre la progression de l'upload. |
14 | 14 |
|
15 |
| -Unfortunately, it won't help us to resume the upload here, as it triggers when the data is *sent*, but was it received by the server? The browser doesn't know. |
| 15 | +Malheureusement, cela ne nous aidera pas à reprendre l'upload ici, car cela ne se déclenche que lorsque les données sont *envoyées*, mais est-ce que le serveur l'a reçu ? Le navigateur ne sait pas. |
16 | 16 |
|
17 |
| -Maybe it was buffered by a local network proxy, or maybe the remote server process just died and couldn't process them, or it was just lost in the middle and didn't reach the receiver. |
| 17 | +Peut-être que cela a été mis en mémoire tampon par un proxy de réseau local, ou peut-être que le processus du serveur distant vient de mourir et n'a pas pu les traiter, ou cela a juste été perdu au milieu et n'a pas atteint le destinataire. |
18 | 18 |
|
19 |
| -That's why this event is only useful to show a nice progress bar. |
| 19 | +C'est pourquoi cet événement n'est utile que pour afficher une belle barre de progression. |
20 | 20 |
|
21 |
| -To resume upload, we need to know *exactly* the number of bytes received by the server. And only the server can tell that, so we'll make an additional request. |
| 21 | +Pour reprendre l'upload, nous devons connaître *exactement* le nombre d'octets reçus par le serveur. Et seul le serveur peut le dire, nous ferons donc une demande supplémentaire. |
22 | 22 |
|
23 |
| -## Algorithm |
| 23 | +## Algorithme |
24 | 24 |
|
25 |
| -1. First, create a file id, to uniquely identify the file we're going to upload: |
| 25 | +1. Créer d'abord un identifiant de fichier pour identifier de manière unique le fichier que nous allons uploader : |
26 | 26 | ```js
|
27 | 27 | let fileId = file.name + '-' + file.size + '-' + +file.lastModifiedDate;
|
28 | 28 | ```
|
29 |
| - That's needed for resume upload, to tell the server what we're resuming. |
| 29 | + Cela est nécessaire pour reprendre l'upload, pour indiquer au serveur ce que nous reprenons. |
30 | 30 |
|
31 |
| - If the name or the size or the last modification date changes, then there'll be another `fileId`. |
| 31 | + Si le nom ou la taille ou la dernière date de modification change, alors il y aura un autre `fileId`. |
32 | 32 |
|
33 |
| -2. Send a request to the server, asking how many bytes it already has, like this: |
| 33 | +2. Envoyer une demande au serveur, lui demandant combien d'octets il possède déjà, comme ceci : |
34 | 34 | ```js
|
35 | 35 | let response = await fetch('status', {
|
36 | 36 | headers: {
|
37 | 37 | 'X-File-Id': fileId
|
38 | 38 | }
|
39 | 39 | });
|
40 | 40 |
|
41 |
| - // The server has that many bytes |
| 41 | + // Le serveur a autant d'octets |
42 | 42 | let startByte = +await response.text();
|
43 | 43 | ```
|
44 | 44 |
|
45 |
| - This assumes that the server tracks file uploads by `X-File-Id` header. Should be implemented at server-side. |
| 45 | + Cela suppose que le serveur effectue le suivi des uploads de fichiers par l'en-tête `X-File-Id`. Doit être implémenté côté serveur. |
46 | 46 |
|
47 |
| - If the file don't yet exist at the server, then the server response should be `0` |
| 47 | + Si le fichier n'existe pas encore sur le serveur, la réponse du serveur doit être `0`. |
48 | 48 |
|
49 |
| -3. Then, we can use `Blob` method `slice` to send the file from `startByte`: |
| 49 | +3. Ensuite, nous pouvons utiliser un `Blob` par la méhtode `slice` pour envoyer le fichier depuis `startByte` : |
50 | 50 | ```js
|
51 | 51 | xhr.open("POST", "upload", true);
|
52 | 52 |
|
53 |
| - // File id, so that the server knows which file we upload |
| 53 | + // Identifiant du fichier, afin que le serveur sache quel fichier nous uploadons |
54 | 54 | xhr.setRequestHeader('X-File-Id', fileId);
|
55 | 55 |
|
56 |
| - // The byte we're resuming from, so the server knows we're resuming |
| 56 | + // L'octet à partir duquel nous reprenons, donc le serveur sait que nous reprenons |
57 | 57 | xhr.setRequestHeader('X-Start-Byte', startByte);
|
58 | 58 |
|
59 | 59 | xhr.upload.onprogress = (e) => {
|
60 | 60 | console.log(`Uploaded ${startByte + e.loaded} of ${startByte + e.total}`);
|
61 | 61 | };
|
62 | 62 |
|
63 |
| - // file can be from input.files[0] or another source |
| 63 | + // le fichier peut provenir de input.files[0] ou d'une autre source |
64 | 64 | xhr.send(file.slice(startByte));
|
65 | 65 | ```
|
66 | 66 |
|
67 |
| - Here we send the server both file id as `X-File-Id`, so it knows which file we're uploading, and the starting byte as `X-Start-Byte`, so it knows we're not uploading it initially, but resuming. |
| 67 | + Ici, nous envoyons au serveur à la fois l'ID du fichier en tant que `X-File-Id`, afin qu'il sache quel fichier nous uploadons, et l'octet de départ en tant que `X-Start-Byte`, afin qu'il sache que nous ne l'uploadons pas de zéro, mais en reprenant. |
68 | 68 |
|
69 |
| - The server should check its records, and if there was an upload of that file, and the current uploaded size is exactly `X-Start-Byte`, then append the data to it. |
| 69 | + Le serveur doit vérifier ses enregistrements et s'il y a eu un upload de ce fichier et que la taille actuellement téléchargée est exactement `X-Start-Byte`, alors il y ajoute les données. |
70 | 70 |
|
71 | 71 |
|
72 |
| -Here's the demo with both client and server code, written on Node.js. |
| 72 | +Voici la démo avec le code client et serveur, écrite sur Node.js. |
73 | 73 |
|
74 |
| -It works only partially on this site, as Node.js is behind another server named Nginx, that buffers uploads, passing them to Node.js when fully complete. |
| 74 | +Cela ne fonctionne que partiellement sur ce site, car Node.js est derrière un autre serveur nommé Nginx, qui met en mémoire tampon les uploads, en les transmettant à Node.js que lorsqu'il est complètement terminé. |
75 | 75 |
|
76 |
| -But you can download it and run locally for the full demonstration: |
| 76 | +Mais vous pouvez le télécharger et l'exécuter localement pour la démonstration complète : |
77 | 77 |
|
78 | 78 | [codetabs src="upload-resume" height=200]
|
79 | 79 |
|
80 |
| -As we can see, modern networking methods are close to file managers in their capabilities -- control over headers, progress indicator, sending file parts, etc. |
| 80 | +Comme nous pouvons le voir, les méthodes de mise en réseau modernes sont proches des gestionnaires de fichiers dans leurs capacités - contrôle des en-têtes, indicateur de progression, envoi de parties de fichier, etc... |
81 | 81 |
|
82 |
| -We can implement resumable upload and much more. |
| 82 | +Nous pouvons implémenter un upload pouvant être repris et bien plus encore. |
0 commit comments