From 16d070c19e29f0242c10bd35c5d37b1a33de0a7a Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sun, 25 Aug 2019 20:14:34 +0300 Subject: [PATCH 1/3] Update error messages for uploads --- src/plugins/uploader.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/uploader.js b/src/plugins/uploader.js index f7d19870..cc2eda68 100644 --- a/src/plugins/uploader.js +++ b/src/plugins/uploader.js @@ -122,7 +122,7 @@ class Uploader { // if the authentication token is incorrect, bail out if (uploadTokens.delete(req.params.token) !== true) { - return abortWithError(Error("Unauthorized")); + return abortWithError(Error("Invalid upload token")); } // if the request does not contain any body data, bail out @@ -198,6 +198,10 @@ class Uploader { busboyInstance.on("finish", () => { doneCallback(); + if (!uploadUrl) { + return res.status(400).json({error: "Missing file"}); + } + // upload was done, send the generated file url to the client res.status(200).json({ url: uploadUrl, From 04e1e004da7ec1b20e936bb03d4f1f58eff8da4e Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sun, 25 Aug 2019 20:14:46 +0300 Subject: [PATCH 2/3] Reset upload input so the same file can be selected again --- client/js/upload.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/js/upload.js b/client/js/upload.js index f23af146..99ea55fb 100644 --- a/client/js/upload.js +++ b/client/js/upload.js @@ -85,6 +85,7 @@ class Uploader { filesChanged() { const files = Array.from(this.uploadInput.files); this.triggerUpload(files); + this.uploadInput.value = ""; // Reset element so you can upload the same file } triggerUpload(files) { From 554c6022302428908e210bf428e0257dd928c728 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sun, 25 Aug 2019 20:23:32 +0300 Subject: [PATCH 3/3] Do not request upload token if there's an upload in process --- client/js/upload.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/js/upload.js b/client/js/upload.js index 99ea55fb..291f9a4e 100644 --- a/client/js/upload.js +++ b/client/js/upload.js @@ -115,8 +115,9 @@ class Uploader { this.fileQueue.push(file); } - // if the queue was empty and we added some files to it, start uploading them - if (wasQueueEmpty && this.fileQueue.length > 0) { + // if the queue was empty and we added some files to it, and there currently + // is no upload in process, request a token to start the upload process + if (wasQueueEmpty && this.xhr === null && this.fileQueue.length > 0) { this.requestToken(); } } @@ -132,10 +133,9 @@ class Uploader { uploadNextFileInQueue(token) { const file = this.fileQueue.shift(); - const xhr = new XMLHttpRequest(); - this.xhr = xhr; + this.xhr = new XMLHttpRequest(); - xhr.upload.addEventListener( + this.xhr.upload.addEventListener( "progress", (e) => { const percent = Math.floor((e.loaded / e.total) * 1000) / 10; @@ -144,26 +144,26 @@ class Uploader { false ); - xhr.onreadystatechange = () => { - if (xhr.readyState === XMLHttpRequest.DONE) { - this.xhr = null; - + this.xhr.onreadystatechange = () => { + if (this.xhr.readyState === XMLHttpRequest.DONE) { let response; try { - response = JSON.parse(xhr.responseText); + response = JSON.parse(this.xhr.responseText); } catch (err) { // This is just a safe guard and should not happen if server doesn't throw any errors. // Browsers break the HTTP spec by aborting the request without reading any response data, // if there is still data to be uploaded. Servers will only error in extreme cases like bad // authentication or server-side errors. response = { - error: `Upload aborted: HTTP ${xhr.status}`, + error: `Upload aborted: HTTP ${this.xhr.status}`, }; } this.handleResponse(response); + this.xhr = null; + // this file was processed, if we still have files in the queue, upload the next one if (this.fileQueue.length > 0) { this.requestToken(); @@ -173,8 +173,8 @@ class Uploader { const formData = new FormData(); formData.append("file", file); - xhr.open("POST", `uploads/new/${token}`); - xhr.send(formData); + this.xhr.open("POST", `uploads/new/${token}`); + this.xhr.send(formData); } handleResponse(response) {