From 2d33e5694b8777ab8d8a47e73c23eab0d1803f18 Mon Sep 17 00:00:00 2001 From: juanf <juanf@ethz.ch> Date: Tue, 14 May 2024 14:52:58 +0200 Subject: [PATCH] BIS-1050: Embeded image import form zip --- .../v3/executor/importer/ImportExecutor.java | 55 ++++++++++++++----- .../xls/importer/utils/FileServerUtils.java | 4 +- .../1/as/services/xls-import/xls-import.py | 8 ++- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/importer/ImportExecutor.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/importer/ImportExecutor.java index 0389e801e59..51363987d1f 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/importer/ImportExecutor.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/importer/ImportExecutor.java @@ -25,6 +25,7 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import ch.ethz.sis.openbis.generic.server.xls.importer.utils.FileServerUtils; import org.springframework.stereotype.Component; import ch.ethz.sis.openbis.generic.asapi.v3.dto.importer.ImportOperation; @@ -51,6 +52,10 @@ public class ImportExecutor implements IImportExecutor private static final String DATA_FOLDER_NAME = "data" + ZIP_PATH_SEPARATOR; + private static final String MISCELLANEOUS_FOLDER_NAME = "miscellaneous" + ZIP_PATH_SEPARATOR; + + private static final String FILE_SERVICES_FOLDER_NAME = MISCELLANEOUS_FOLDER_NAME + "file-service" + ZIP_PATH_SEPARATOR; + private static final String XLS_EXTENSION = "." + "xls"; private static final String XLSX_EXTENSION = "." + "xlsx"; @@ -74,25 +79,24 @@ public class ImportExecutor implements IImportExecutor final Map<String, String> importValues = uncompressedImportData.getImportValues() != null ? uncompressedImportData.getImportValues().stream().collect(Collectors.toMap(ImportValue::getName, ImportValue::getValue)) : null; - importXls(context, operation, scripts, importValues, uncompressedImportData.getFile()); + importXls(context, operation, scripts, importValues, uncompressedImportData.getFile(), null); } else if (importData instanceof ZipImportData) { // ZIP file + final Map<String, String> scripts = new HashMap<>(); + final Map<String, String> importValues = new HashMap<>(); + byte[] xlsFileContent = null; final ZipImportData zipImportData = (ZipImportData) importData; try (final ZipInputStream zip = new ZipInputStream(new ByteArrayInputStream(zipImportData.getFile()))) { - final Map<String, String> scripts = new HashMap<>(); - final Map<String, String> importValues = new HashMap<>(); - byte[] xlsFileContent = null; - ZipEntry entry; while ((entry = zip.getNextEntry()) != null) { final String entryName = entry.getName(); if (entry.isDirectory()) { - if (!SCRIPTS_FOLDER_NAME.equals(entryName) && !DATA_FOLDER_NAME.equals(entryName)) + if (!SCRIPTS_FOLDER_NAME.equals(entryName) && !DATA_FOLDER_NAME.equals(entryName) && !MISCELLANEOUS_FOLDER_NAME.equals(entryName)) { throw UserFailureException.fromTemplate("Illegal directory '%s' is found inside the imported file.", entryName); } @@ -121,15 +125,16 @@ public class ImportExecutor implements IImportExecutor } } } + } - if (xlsFileContent != null) - { - importXls(context, operation, scripts, importValues, xlsFileContent); - } else - { - throw UserFailureException.fromTemplate("XLS file not found in the root of the imported ZIP file."); - } + if (xlsFileContent != null) + { + importXls(context, operation, scripts, importValues, xlsFileContent, zipImportData.getFile()); + } else + { + throw UserFailureException.fromTemplate("XLS file not found in the root of the imported ZIP file."); } + } else { throw UserFailureException.fromTemplate("Unknown instance of import data '%s'.", @@ -142,7 +147,8 @@ public class ImportExecutor implements IImportExecutor } private static void importXls(final IOperationContext context, final ImportOperation operation, final Map<String, String> scripts, - final Map<String, String> importValues, final byte[] xlsContent) + final Map<String, String> importValues, final byte[] xlsContent, byte[] zipImportDataOrNull) + throws IOException { final IApplicationServerInternalApi applicationServerApi = CommonServiceProvider.getApplicationServerApi(); final ImportOptions importOptions = operation.getImportOptions(); @@ -158,6 +164,27 @@ public class ImportExecutor implements IImportExecutor importValues, ImportModes.valueOf(importOptions.getMode().name()), importerImportOptions, "DEFAULT"); xlsImport.importXLS(xlsContent); + if (zipImportDataOrNull != null) + { + importZipData(zipImportDataOrNull); + } } + public static void importZipData(byte[] zipImportDataOrNull) throws IOException + { + try (final ZipInputStream zip = new ZipInputStream(new ByteArrayInputStream(zipImportDataOrNull))) + { + ZipEntry entry; + while ((entry = zip.getNextEntry()) != null) + { + final String filePath = entry.getName(); + if (!entry.isDirectory() && filePath.startsWith(FILE_SERVICES_FOLDER_NAME)) + { + String fileServicePath = ZIP_PATH_SEPARATOR + filePath.substring(FILE_SERVICES_FOLDER_NAME.length()); + byte[] fileBytes = zip.readAllBytes(); + FileServerUtils.write(fileServicePath, fileBytes); + } + } + } + } } diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/utils/FileServerUtils.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/utils/FileServerUtils.java index 32160bd9de0..1784e017998 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/utils/FileServerUtils.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/utils/FileServerUtils.java @@ -43,6 +43,8 @@ public class FileServerUtils public static Path write(String filePath, byte[] bytes) throws IOException { - return Files.write(getFilePath(filePath), bytes); + Path filePathAsPath = getFilePath(filePath); + Files.createDirectories(filePathAsPath); + return Files.write(filePathAsPath, bytes); } } diff --git a/ui-admin/src/core-plugins/admin/1/as/services/xls-import/xls-import.py b/ui-admin/src/core-plugins/admin/1/as/services/xls-import/xls-import.py index 393bb0b98b9..dce1366af7d 100644 --- a/ui-admin/src/core-plugins/admin/1/as/services/xls-import/xls-import.py +++ b/ui-admin/src/core-plugins/admin/1/as/services/xls-import/xls-import.py @@ -10,6 +10,7 @@ from java.io import File from java.lang import Long from java.lang import System from java.nio.file import Path +from ch.ethz.sis.openbis.generic.server.asapi.v3.executor.importer import ImportExecutor def get_update_mode(parameters): update_mode = parameters.get('update_mode', 'FAIL_IF_EXISTS') @@ -48,6 +49,7 @@ def process(context, parameters): if method == "import": zip = parameters.get('zip', False) temp = None + zip_bytes = None if zip: # Zip mode uses xls_base64 for all multiple XLS + script files zip_bytes = base64.b64decode(parameters.get('xls_base64')) temp = File.createTempFile("temp", Long.toString(System.nanoTime())) @@ -73,13 +75,13 @@ def process(context, parameters): xls_base64_string = parameters.get('xls_base64', None) if xls_base64_string is not None: parameters.put('xls', [ base64.b64decode(xls_base64_string) ]) - result = _import(context, parameters) + result = _import(context, parameters, zip_bytes) if temp is not None: FileUtils.deleteDirectory(temp) return result -def _import(context, parameters): +def _import(context, parameters, zip_bytes): """ Excel import AS service. For extensive documentation of usage and Excel layout, @@ -120,5 +122,7 @@ def _import(context, parameters): xls_byte_arrays = parameters.get('xls', None) for xls_byte_array in xls_byte_arrays: ids.addAll(importXls.importXLS(xls_byte_array)) + if zip_bytes is not None: + ImportExecutor.importZipData(zip_bytes) return ids -- GitLab