diff --git a/src/backend/src/filesystem/batch/commands.js b/src/backend/src/filesystem/batch/commands.js index 782541d2f..4ebe6cf60 100644 --- a/src/backend/src/filesystem/batch/commands.js +++ b/src/backend/src/filesystem/batch/commands.js @@ -26,6 +26,7 @@ const { OperationFrame } = require('../../services/OperationTraceService'); const { HLMkShortcut } = require('../hl_operations/hl_mkshortcut'); const { HLMkLink } = require('../hl_operations/hl_mklink'); const { HLRemove } = require('../hl_operations/hl_remove'); +const { safeHasOwnProperty } = require('../../util/safety'); class BatchCommand extends AdvancedBase { static FEATURES = [ @@ -36,7 +37,7 @@ class BatchCommand extends AdvancedBase { let x = Context.get(); const operationTraceSvc = x.get('services').get('operationTrace'); const frame = await operationTraceSvc.add_frame(`batch:${ this.name}`); - if ( parameters.hasOwnProperty('item_upload_id') ) { + if ( safeHasOwnProperty(parameters, 'item_upload_id') ) { frame.attr('gui_metadata', { ...(frame.get_attr('gui_metadata') || {}), item_upload_id: parameters.item_upload_id, @@ -149,6 +150,8 @@ class WriteCommand extends BatchCommand { operation_id: parameters.operation_id, item_upload_id: parameters.item_upload_id, app_id: app ? app.id : null, + + thumbnail: parameters.thumbnail, }); this.provideValue('result', response); diff --git a/src/backend/src/filesystem/hl_operations/hl_write.js b/src/backend/src/filesystem/hl_operations/hl_write.js index 589538a66..c2adefece 100644 --- a/src/backend/src/filesystem/hl_operations/hl_write.js +++ b/src/backend/src/filesystem/hl_operations/hl_write.js @@ -111,6 +111,9 @@ class HLWrite extends HLFilesystemOperation { create_missing_parents: new FlagParam('create_missing_parents', { optional: true }), user: new UserParam(), + // client-provided thumbnail as a base64 string + thumbnail: new StringParam('thumbnail', { optional: true }), + // file: multer.File }; @@ -300,12 +303,14 @@ class HLWrite extends HLFilesystemOperation { let thumbnail_promise = new TeePromise(); if ( await parent.isAppDataDirectory() || values.no_thumbnail ) { thumbnail_promise.resolve(undefined); + } else if ( values.thumbnail ) { + // Use the thumbnail provided by the client (base64 string) + thumbnail_promise.resolve(values.thumbnail); } else { (async () => { const reason = await (async () => { const { mime } = this.modules; const thumbnails = context.get('services').get('thumbnails'); - if ( values.thumbnail ) return 'already thumbnail'; const content_type = mime.contentType(target_name); this.log.debug('CONTENT TYPE', content_type); diff --git a/src/backend/src/routers/filesystem_api/batch/all.js b/src/backend/src/routers/filesystem_api/batch/all.js index d39c8e521..1c0a6388a 100644 --- a/src/backend/src/routers/filesystem_api/batch/all.js +++ b/src/backend/src/routers/filesystem_api/batch/all.js @@ -18,7 +18,6 @@ */ const APIError = require('../../../api/APIError'); const eggspress = require('../../../api/eggspress'); -const config = require('../../../config'); const { Context } = require('../../../util/context'); const Busboy = require('busboy'); const { BatchExecutor } = require('../../../filesystem/batch/BatchExecutor'); @@ -227,6 +226,11 @@ module.exports = eggspress('/batch', { const op_spec = pending_operations.shift(); + // Copy thumbnail from fileinfo to the file object if provided + if ( file.thumbnail ) { + op_spec.thumbnail = file.thumbnail; + } + // index in response_promises is first null value const index = response_promises.findIndex(p => p === null); response_promises[index] = batch_exe.exec_op(req, op_spec, file); diff --git a/src/backend/src/routers/filesystem_api/write.js b/src/backend/src/routers/filesystem_api/write.js index c5975430d..44824fdc7 100644 --- a/src/backend/src/routers/filesystem_api/write.js +++ b/src/backend/src/routers/filesystem_api/write.js @@ -44,7 +44,7 @@ module.exports = eggspress(['/up', '/write'], { // fsNode: new FSNodeParam('path'), // target: new FSNodeParam('shortcut_to', { optional: true }), // } -}, async (req, res, next) => { +}, async (req, res, _next) => { // Note: parameters moved here because the parameter // middleware won't work while using busboy const parameters = { @@ -63,7 +63,7 @@ module.exports = eggspress(['/up', '/write'], { const x = Context.get(); let frame; - const frame_meta_ready = async () => { + async () => { const operationTraceSvc = x.get('services').get('operationTrace'); frame = (await operationTraceSvc.add_frame('api:/write')) .attr('gui_metadata', { @@ -183,6 +183,8 @@ module.exports = eggspress(['/up', '/write'], { file: uploaded_file, app_id: app ? app.id : null, + + thumbnail: req.body.thumbnail, }); if ( frame ) frame.done();