From 8a8298ad46d11fd6456080d433fdd58e54e1449e Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Mon, 22 Nov 2021 12:25:36 +0100 Subject: [PATCH] web client: improve file upload --- httpd/api_utils.go | 2 ++ httpd/httpd_test.go | 4 ++-- httpd/internal_test.go | 3 +++ openapi/openapi.yaml | 10 ++++++++++ sftpgo.json | 2 +- templates/webclient/files.html | 33 +++++++++++++++++++++++++++------ 6 files changed, 45 insertions(+), 9 deletions(-) diff --git a/httpd/api_utils.go b/httpd/api_utils.go index 86ef8fd2..6997828f 100644 --- a/httpd/api_utils.go +++ b/httpd/api_utils.go @@ -98,6 +98,8 @@ func getMappedStatusCode(err error) int { statusCode = http.StatusForbidden case os.ErrNotExist: statusCode = http.StatusNotFound + case common.ErrQuotaExceeded: + statusCode = http.StatusRequestEntityTooLarge default: statusCode = http.StatusInternalServerError } diff --git a/httpd/httpd_test.go b/httpd/httpd_test.go index 79216e05..a39fc253 100644 --- a/httpd/httpd_test.go +++ b/httpd/httpd_test.go @@ -10372,7 +10372,7 @@ func TestWebUploadSFTP(t *testing.T) { req.Header.Add("Content-Type", writer.FormDataContentType()) setBearerForReq(req, webAPIToken) rr = executeRequest(req) - checkResponseCode(t, http.StatusInternalServerError, rr) + checkResponseCode(t, http.StatusRequestEntityTooLarge, rr) assert.Contains(t, rr.Body.String(), "denying write due to space limit") // delete the file req, err = http.NewRequest(http.MethodDelete, userFilesPath+"?path=file.txt", nil) @@ -10388,7 +10388,7 @@ func TestWebUploadSFTP(t *testing.T) { req.Header.Add("Content-Type", writer.FormDataContentType()) setBearerForReq(req, webAPIToken) rr = executeRequest(req) - checkResponseCode(t, http.StatusInternalServerError, rr) + checkResponseCode(t, http.StatusRequestEntityTooLarge, rr) assert.Contains(t, rr.Body.String(), "denying write due to space limit") _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK) diff --git a/httpd/internal_test.go b/httpd/internal_test.go index 4d74f783..b0769d68 100644 --- a/httpd/internal_test.go +++ b/httpd/internal_test.go @@ -317,6 +317,9 @@ func TestMappedStatusCode(t *testing.T) { err = os.ErrNotExist code = getMappedStatusCode(err) assert.Equal(t, http.StatusNotFound, code) + err = common.ErrQuotaExceeded + code = getMappedStatusCode(err) + assert.Equal(t, http.StatusRequestEntityTooLarge, code) err = os.ErrClosed code = getMappedStatusCode(err) assert.Equal(t, http.StatusInternalServerError, code) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index a4d628d7..a395204b 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -124,6 +124,8 @@ paths: $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' + '413': + $ref: '#/components/responses/RequestEntityTooLarge' '500': $ref: '#/components/responses/InternalServerError' default: @@ -3610,6 +3612,8 @@ paths: $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' + '413': + $ref: '#/components/responses/RequestEntityTooLarge' '500': $ref: '#/components/responses/InternalServerError' default: @@ -3750,6 +3754,12 @@ components: application/json: schema: $ref: '#/components/schemas/ApiResponse' + RequestEntityTooLarge: + description: Request Entity Too Large, max allowed size exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' InternalServerError: description: Internal Server Error content: diff --git a/sftpgo.json b/sftpgo.json index 137477b9..fa98e4d5 100644 --- a/sftpgo.json +++ b/sftpgo.json @@ -215,8 +215,8 @@ ], "templates_path": "templates", "static_files_path": "static", - "backups_path": "backups", "openapi_path": "openapi", + "backups_path": "backups", "web_root": "", "certificate_file": "", "certificate_key_file": "", diff --git a/templates/webclient/files.html b/templates/webclient/files.html index 6f6089d2..be307cb1 100644 --- a/templates/webclient/files.html +++ b/templates/webclient/files.html @@ -84,15 +84,15 @@ + + {{end}} {{define "extra_js"}} @@ -329,6 +336,13 @@ }); } + function keepAlive() { + $.ajax({ + url: '{{.ProfileURL}}', + timeout: 15000 + }); + } + $(document).ready(function () { $("#create_dir_form").submit(function (event) { event.preventDefault(); @@ -368,7 +382,7 @@ $("#upload_files_form").submit(function (event){ event.preventDefault(); - $('uploadFilesModal').modal('hide'); + var keepAliveTimer = setInterval(keepAlive, 90000); var path = '{{.FilesURL}}?path={{.CurrentDir}}'; $.ajax({ url: path, @@ -377,11 +391,18 @@ processData: false, contentType: false, headers: { 'X-CSRF-TOKEN': '{{.CSRFToken}}' }, - timeout: 15000, + timeout: 0, + beforeSend: function () { + $('#uploadFilesModal').modal('hide'); + $('#spinnerModal').modal('show'); + }, success: function (result) { + clearInterval(keepAliveTimer); location.reload(); }, error: function ($xhr, textStatus, errorThrown) { + clearInterval(keepAliveTimer); + $('#spinnerModal').modal('hide'); var txt = "Error uploading files"; if ($xhr) { var json = $xhr.responseJSON;