From 4208bb871c5541c377d08c1580ec987553e9b9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20Spie=C3=9F?= Date: Wed, 29 Mar 2023 12:46:36 +0200 Subject: [PATCH 1/3] fix(refs T31971): replace reserved chars in filenames As the tus endpoint breaks with 400 when uploading files with certain characters within them, the fileName is cleaned from those malfunctioning characters before adding it to the Uppy store (and eventually uploading them, as auto resume is activated). The characters to be replaced were chosen based on a manual test that i conducted - while i could not produce a file containing a forward slash on my linux machine, all other characters have proven to break the endpoint. Maybe i missed a character, then it will have to be added to the list. The fix revealed another bug - file names containing a colon : now broke the frontend, because the colon is used as a separator in getFileInfo. As the conversion (from object to fileString and vice versa) is not needed but is a remainder from the Uppy refactoring (as far as i could understand it), it is dropped altogether, and the file object is directly passed into DpUploadFile. --- src/components/core/DpUpload/DpUpload.vue | 57 ++++++++++++++++++- .../core/DpUpload/DpUploadedFile.vue | 20 ++++--- .../core/DpUpload/DpUploadedFileList.vue | 14 +---- 3 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/components/core/DpUpload/DpUpload.vue b/src/components/core/DpUpload/DpUpload.vue index c9e4c7d59..030717624 100644 --- a/src/components/core/DpUpload/DpUpload.vue +++ b/src/components/core/DpUpload/DpUpload.vue @@ -60,7 +60,7 @@ export default { /** * Maximum number of files that can be uploaded. - * By default its a single file upload. + * By default, it's allowed to upload a single file. */ maxNumberOfFiles: { type: Number, @@ -95,6 +95,60 @@ export default { return b ? b.pop() : '' }, + /** + * Fires immediately before a file is added to the Uppy store. + * + * The hook is used here to clean file names from characters that would + * break the tus endpoint. This could as well be implemented within the backend. + * + * @param currentFile + * @param files + * @return {(*&{meta: (*&{name: *}), name: *})|*} + * @see https://github.com/transloadit/uppy/blob/main/packages/@uppy/core/src/Uppy.js#L503 + */ + handleOnBeforeFileAdded (currentFile, files) { + let fileName = currentFile.name + + /* + * This is not an exhaustive list - the characters have been determined + * simply by trying out which break or do not break the tus endpoint. + */ + const reservedCharacters = [ + '?', + '#', + '&', + '\'', + '"', + '/', + ':', + '\\' + ] + + /* + * For reasons i could not figure out, the for loop was needed here + * to reliably access the item that is looped over. When using forEach, + * strangely it always held the value of currentFile. + */ + for (let i = 0; i < reservedCharacters.length; i++) { + if (fileName.includes(reservedCharacters[i])) { + fileName = fileName.replace(reservedCharacters[i], '_') + } + } + + if (fileName !== currentFile.name) { + return { + ...currentFile, + name: fileName, + meta: { + ...currentFile.meta, + name: fileName + } + } + } else { + return currentFile + } + }, + initialize () { const locale = { strings: { ...de().strings, ...this.translations } } this.uppy = new Uppy({ @@ -106,6 +160,7 @@ export default { maxFileSize: this.maxFileSize, maxNumberOfFiles: this.maxNumberOfFiles }, + onBeforeFileAdded: this.handleOnBeforeFileAdded, locale: locale }) diff --git a/src/components/core/DpUpload/DpUploadedFile.vue b/src/components/core/DpUpload/DpUploadedFile.vue index c3589e006..e44ac79e0 100644 --- a/src/components/core/DpUpload/DpUploadedFile.vue +++ b/src/components/core/DpUpload/DpUploadedFile.vue @@ -15,8 +15,10 @@ - {{ file.name }} - ({{ file.size }}) + + {{ file.name }} + + ({{ fileSize }})