|
1 | | -import * as cache from './cache.ts'; |
2 | 1 | import * as dependencies from './dependencies.ts'; |
3 | 2 | import { electronApi } from './electronApi.ts'; |
4 | 3 |
|
@@ -213,170 +212,3 @@ export const fileName = (filePath: string): string => { |
213 | 212 | export const sleep = (ms: number): Promise<void> => { |
214 | 213 | return new Promise((resolve) => setTimeout(resolve, ms)); |
215 | 214 | }; |
216 | | - |
217 | | -// A method to retrieve the size of a remote file, if possible. |
218 | | - |
219 | | -export const remoteFileSize = async (url: string): Promise<number> => { |
220 | | - // Check the cache first. |
221 | | - |
222 | | - try { |
223 | | - const size = await cache.remoteFileSize(url); |
224 | | - |
225 | | - if (size !== undefined) { |
226 | | - return size; |
227 | | - } |
228 | | - } catch {} |
229 | | - |
230 | | - // Try a HEAD request first to get the content-length header. |
231 | | - |
232 | | - try { |
233 | | - const head = await fetch(url, { method: 'HEAD' }); |
234 | | - const contentLength = head.headers.get('content-length'); |
235 | | - |
236 | | - if (head.ok && contentLength && /^\d+$/.test(contentLength)) { |
237 | | - const size = Number(contentLength); |
238 | | - |
239 | | - await cache.setRemoteFileSize(url, size); |
240 | | - |
241 | | - return size; |
242 | | - } |
243 | | - } catch {} |
244 | | - |
245 | | - // If that doesn't work, try a GET request with a Range header to get the content-range header. |
246 | | - |
247 | | - try { |
248 | | - const res = await fetch(url, { headers: { Range: 'bytes=0-0' } }); |
249 | | - const contentRange = res.headers.get('content-range'); |
250 | | - const match = contentRange?.match(/\/(\d+)$/); |
251 | | - |
252 | | - if (res.ok && match) { |
253 | | - const size = Number(match[1]); |
254 | | - |
255 | | - await cache.setRemoteFileSize(url, size); |
256 | | - |
257 | | - return size; |
258 | | - } |
259 | | - } catch {} |
260 | | - |
261 | | - const size = 0; // Unknown size. |
262 | | - |
263 | | - await cache.setRemoteFileSize(url, size); |
264 | | - |
265 | | - return size; |
266 | | -}; |
267 | | - |
268 | | -// A method to download a remote file and track the progress of the download. |
269 | | - |
270 | | -export const downloadRemoteFile = async (url: string, onProgress: (percent: number) => void): Promise<Uint8Array> => { |
271 | | - // Check the cache first. |
272 | | - |
273 | | - try { |
274 | | - const data = await cache.remoteFile(url); |
275 | | - |
276 | | - if (data) { |
277 | | - for (let percent = 0; percent <= 100; percent += 2) { |
278 | | - await sleep(1); |
279 | | - |
280 | | - onProgress(percent); |
281 | | - } |
282 | | - |
283 | | - return data; |
284 | | - } |
285 | | - } catch {} |
286 | | - |
287 | | - // Download the file in chunks and track the progress. |
288 | | - |
289 | | - const res = await fetch(url); |
290 | | - |
291 | | - if (!res.ok) { |
292 | | - throw new Error(`HTTP ${res.status} was returned while trying to download ${url}.`); |
293 | | - } |
294 | | - |
295 | | - if (!res.body) { |
296 | | - throw new Error('ReadableStream is not supported in this browser.'); |
297 | | - } |
298 | | - |
299 | | - // Start with 0% progress. |
300 | | - |
301 | | - onProgress(0); |
302 | | - |
303 | | - // Try to get the total size of the file from the content-length header or the cache, if possible, to be able to |
304 | | - // compute the progress. If not, we'll just show 0% until the download is complete and then show 100%. |
305 | | - |
306 | | - let totalNbOfBytes = 0; |
307 | | - const contentLength = res.headers.get('content-length'); |
308 | | - |
309 | | - if (contentLength && /^\d+$/.test(contentLength)) { |
310 | | - totalNbOfBytes = Number(contentLength); |
311 | | - |
312 | | - await cache.setRemoteFileSize(url, totalNbOfBytes); |
313 | | - } else { |
314 | | - totalNbOfBytes = await remoteFileSize(url); |
315 | | - } |
316 | | - |
317 | | - // Read the response body in chunks and track the progress. |
318 | | - |
319 | | - const reader = res.body.getReader(); |
320 | | - let oldPercent = 0; |
321 | | - let crtNbOfBytes = 0; |
322 | | - const buffer = totalNbOfBytes ? new Uint8Array(totalNbOfBytes) : undefined; |
323 | | - const chunks: Uint8Array[] = buffer ? [] : []; |
324 | | - |
325 | | - while (true) { |
326 | | - const { done, value } = await reader.read(); |
327 | | - |
328 | | - if (done) { |
329 | | - break; |
330 | | - } |
331 | | - |
332 | | - if (!value) { |
333 | | - continue; |
334 | | - } |
335 | | - |
336 | | - if (buffer) { |
337 | | - buffer.set(value, crtNbOfBytes); |
338 | | - } else { |
339 | | - chunks.push(value); |
340 | | - } |
341 | | - |
342 | | - crtNbOfBytes += value.length; |
343 | | - |
344 | | - if (totalNbOfBytes) { |
345 | | - const percent = Math.floor((100 * crtNbOfBytes) / totalNbOfBytes); |
346 | | - |
347 | | - if (percent > oldPercent) { |
348 | | - oldPercent = percent; |
349 | | - |
350 | | - onProgress(percent); |
351 | | - } |
352 | | - } |
353 | | - } |
354 | | - |
355 | | - if (!totalNbOfBytes) { |
356 | | - onProgress(100); |
357 | | - } |
358 | | - |
359 | | - let data: Uint8Array; |
360 | | - |
361 | | - if (buffer) { |
362 | | - data = crtNbOfBytes === totalNbOfBytes ? buffer : buffer.subarray(0, crtNbOfBytes); |
363 | | - } else { |
364 | | - let offset = 0; |
365 | | - |
366 | | - data = new Uint8Array(crtNbOfBytes); |
367 | | - |
368 | | - for (const chunk of chunks) { |
369 | | - data.set(chunk, offset); |
370 | | - |
371 | | - offset += chunk.length; |
372 | | - } |
373 | | - } |
374 | | - |
375 | | - // Try to cache the remote file. |
376 | | - |
377 | | - try { |
378 | | - await cache.setRemoteFile(url, data); |
379 | | - } catch {} |
380 | | - |
381 | | - return data; |
382 | | -}; |
0 commit comments