From bb15daae6b962f11f39ed8cad65d8f096712c08c Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Mon, 16 Apr 2018 21:41:05 +0200 Subject: [PATCH] Improved file upload --- scripts/Actions/Upload.ts | 41 +++++++++++++++++++----------- scripts/Utils/fetchWithProgress.ts | 19 ++++++++++++++ 2 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 scripts/Utils/fetchWithProgress.ts diff --git a/scripts/Actions/Upload.ts b/scripts/Actions/Upload.ts index bb0e83e3..f516c2c3 100644 --- a/scripts/Actions/Upload.ts +++ b/scripts/Actions/Upload.ts @@ -1,5 +1,6 @@ import AnimeNotifier from "../AnimeNotifier" import StatusMessage from "../StatusMessage" +import { fetchWithProgress } from "../Utils/fetchWithProgress" // Select file export function selectFile(arn: AnimeNotifier, button: HTMLButtonElement) { @@ -54,29 +55,39 @@ function uploadFile(file: File, fileType: string, endpoint: string, arn: AnimeNo let reader = new FileReader() reader.onloadend = async () => { - arn.statusMessage.showInfo(`Uploading ${fileType}...`, 60000) + let megaBytes = reader.result.byteLength / 1024 / 1024 + arn.statusMessage.showInfo(`Uploading ${fileType}...${megaBytes.toFixed(1)} MB`, -1) - let response = await fetch(endpoint, { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/octet-stream" - }, - body: reader.result - }) + try { + let responseText = await fetchWithProgress(endpoint, { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/octet-stream" + }, + body: reader.result + }, e => { + if(!e.lengthComputable) { + return + } - if(endpoint === "/api/upload/avatar") { - let newURL = await response.text() - updateSideBarAvatar(newURL) - } + let progress = e.loaded / e.total * 100 + arn.statusMessage.showInfo(`Uploading ${fileType}...${progress.toFixed(1)}%`, -1) + }) - if(response.ok) { arn.statusMessage.showInfo(`Successfully uploaded your new ${fileType}.`) - } else { + + if(endpoint === "/api/upload/avatar") { + // We received the new avatar URL + updateSideBarAvatar(responseText) + } + } catch(err) { arn.statusMessage.showError(`Failed uploading your new ${fileType}.`) + console.error(err) } } + arn.statusMessage.showInfo(`Reading ${fileType} from disk...`, -1) reader.readAsArrayBuffer(file) } diff --git a/scripts/Utils/fetchWithProgress.ts b/scripts/Utils/fetchWithProgress.ts new file mode 100644 index 00000000..da382475 --- /dev/null +++ b/scripts/Utils/fetchWithProgress.ts @@ -0,0 +1,19 @@ +export function fetchWithProgress(url, opts: RequestInit, onProgress: ((this: XMLHttpRequest, ev: ProgressEvent) => any) | null): Promise { + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest() + xhr.open(opts.method || "GET", url) + + for(let k in opts.headers || {}) { + xhr.setRequestHeader(k, opts.headers[k]) + } + + xhr.onload = e => resolve(xhr.responseText) + xhr.onerror = reject + + if(xhr.upload && onProgress) { + xhr.upload.onprogress = onProgress + } + + xhr.send(opts.body) + }) +}