aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@protonmail.com>2023-11-08 18:38:44 +0100
committerJohn Molakvoæ <skjnldsv@protonmail.com>2023-12-05 12:10:39 +0100
commitf89ef392b32012c80a0b04e4a14f9366169b5a57 (patch)
tree42867513503f2e31a98baf80c45f874bc662dfa2 /apps
parent431ac74d788535c29c97a6f7f9746b16af37afa8 (diff)
downloadnextcloud-server-f89ef392b32012c80a0b04e4a14f9366169b5a57.tar.gz
nextcloud-server-f89ef392b32012c80a0b04e4a14f9366169b5a57.zip
fix(files): better upload error handling
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/lib/Connector/Sabre/QuotaPlugin.php6
-rw-r--r--apps/files/src/components/NavigationQuota.vue4
-rw-r--r--apps/files/src/views/FilesList.vue36
3 files changed, 44 insertions, 2 deletions
diff --git a/apps/dav/lib/Connector/Sabre/QuotaPlugin.php b/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
index ddf4b2773e0..1eed3d0d778 100644
--- a/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
@@ -193,6 +193,8 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
$parentPath = '';
}
$req = $this->server->httpRequest;
+
+ // If chunked upload
if ($req->getHeader('OC-Chunked')) {
$info = \OC_FileChunking::decodeName($newName);
$chunkHandler = $this->getFileChunking($info);
@@ -202,6 +204,10 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
// use target file name for free space check in case of shared files
$path = rtrim($parentPath, '/') . '/' . $info['name'];
}
+
+ // Strip any duplicate slashes
+ $path = str_replace('//', '/', $path);
+
$freeSpace = $this->getFreeSpace($path);
if ($freeSpace >= 0 && $length > $freeSpace) {
if (isset($chunkHandler)) {
diff --git a/apps/files/src/components/NavigationQuota.vue b/apps/files/src/components/NavigationQuota.vue
index ab049779921..4dab7b53a4b 100644
--- a/apps/files/src/components/NavigationQuota.vue
+++ b/apps/files/src/components/NavigationQuota.vue
@@ -89,7 +89,7 @@ export default {
mounted() {
// Warn the user if the available storage is 0 on page load
- if (this.storageStats?.free === 0) {
+ if (this.storageStats?.free <= 0) {
this.showStorageFullWarning()
}
},
@@ -123,7 +123,7 @@ export default {
}
// Warn the user if the available storage changed from > 0 to 0
- if (this.storageStats?.free !== 0 && response.data.data?.free === 0) {
+ if (this.storageStats?.free > 0 && response.data.data?.free <= 0) {
this.showStorageFullWarning()
}
diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue
index 2fabbc7c5fa..93301bb54f3 100644
--- a/apps/files/src/views/FilesList.vue
+++ b/apps/files/src/views/FilesList.vue
@@ -58,6 +58,7 @@
:destination="currentFolder"
:multiple="true"
class="files-list__header-upload-button"
+ @failed="onUploadFail"
@uploaded="onUpload" />
</template>
</BreadCrumbs>
@@ -126,6 +127,8 @@ import { Folder, Node, Permission } from '@nextcloud/files'
import { getCapabilities } from '@nextcloud/capabilities'
import { join, dirname } from 'path'
import { orderBy } from 'natural-orderby'
+import { Parser } from 'xml2js'
+import { showError } from '@nextcloud/dialogs'
import { translate, translatePlural } from '@nextcloud/l10n'
import { Type } from '@nextcloud/sharing'
import { UploadPicker } from '@nextcloud/upload'
@@ -515,6 +518,39 @@ export default defineComponent({
}
},
+ async onUploadFail(upload: Upload) {
+ const status = upload.response?.status || 0
+
+ // Check known status codes
+ if (status === 507) {
+ showError(this.t('files', 'Not enough free space'))
+ return
+ } else if (status === 404 || status === 409) {
+ showError(this.t('files', 'Target folder does not exist any more'))
+ return
+ } else if (status === 403) {
+ showError(this.t('files', 'Operation is blocked by access control'))
+ return
+ } else if (status !== 0) {
+ showError(this.t('files', 'Error when assembling chunks, status code {status}', { status }))
+ return
+ }
+
+ // Else we try to parse the response error message
+ try {
+ const parser = new Parser({ trim: true, explicitRoot: false })
+ const response = await parser.parseStringPromise(upload.response?.data)
+ const message = response['s:message'][0] as string
+ if (typeof message === 'string' && message.trim() !== '') {
+ // Unfortunatly, the server message is not translated
+ showError(this.t('files', 'Error during upload: {message}', { message }))
+ return
+ }
+ } catch (error) {}
+
+ showError(this.t('files', 'Unknown error during upload'))
+ },
+
openSharingSidebar() {
if (window?.OCA?.Files?.Sidebar?.setActiveTab) {
window.OCA.Files.Sidebar.setActiveTab('sharing')