Class DefaultStorageService
- All Implemented Interfaces:
StorageService
- Author:
- Chad Harchar (charchar), Samarth Dhruva (samarthd)
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classA simple object holding information about aZipEntrywhich failed validation for some reason.static classA simple object holding information about the results of extracting the contents of a zip file. -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final AssetService<Asset>protected AssetStorageUtilsprotected static final Stringprotected static final Stringprotected final FileUploadStateService<FileUploadState>protected final FolderService<Folder>protected final ImageOperationServiceprotected final InternalAssetPropertiesstatic final Stringprotected final jakarta.servlet.MultipartConfigElementstatic final Stringprotected final com.broadleafcommerce.common.extension.data.DataRouteReferenceprotected final StorageProviderprotected final com.broadleafcommerce.common.extension.TypeFactorystatic final String -
Constructor Summary
ConstructorsConstructorDescriptionDefaultStorageService(AssetService<Asset> assetService, FolderService<Folder> folderService, jakarta.servlet.MultipartConfigElement multipartConfigElement, StorageProvider storageProvider, InternalAssetProperties internalAssetProperties, com.broadleafcommerce.common.extension.TypeFactory typeFactory, ImageOperationService imageOperationService, FileUploadStateService<FileUploadState> fileUploadStateService, jakarta.activation.FileTypeMap mimeFileTypeMap, AssetUrlGenerationHelper assetUrlGenerationHelper, com.broadleafcommerce.common.extension.data.DataRouteReference reference) -
Method Summary
Modifier and TypeMethodDescriptionvoidaddAttributesToAsset(@NonNull Asset asset, @NonNull ResourceWithMetadata resource) Responsible for adding any attributes to the asset that are derived from the uploadedResource.voidaddAttributesToAsset(@NonNull Asset asset, @NonNull File file) Responsible for adding any attributes to the asset that are derived from the uploaded file.protected voidaddImageAttributes(@NonNull Asset asset, @NonNull Dimension imageDimension) protected voidbatchOptimizeFiles(Map<String, File> filesToOptimizeByNormalizedPath) Delegates toImageOperationServiceto optimize the given files as a batch.protected StringbuildErrorMessage(@NonNull List<DefaultStorageService.ZipEntryValidationError> errors) protected voidbuildFolderAndPutInMap(String directoryPath, Map<String, Folder> foldersByNormalizedPath, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Given a directory path that was found in a zip file, build aFolderfor it and put it in the givenfoldersByPathmap.createAllFolders(Map<String, Folder> foldersToCreateByNormalizedPath, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, Asset assetRequest) Creates all of the givenFoldersin the data store, and returns the created items.createAssetsForSuccessfullyUploadedFiles(DefaultStorageService.ZipExtractionResult zipExtractionResult, Map<String, String> contextDiscriminatedUrlsByNormalizedPath, Map<String, Folder> createdFoldersByNormalizedPath, BulkAddResourcesResponse addResourcesResponse, Asset assetRequest, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) CreatesAssetsin the data store for the files that were successfully uploaded to the storage provider.protected StringcreateUniqueUrlFromFilename(String filename, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Creates a URL for the given filename.protected StringcreateUniqueUrlFromFilename(String filename, String folderName, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Creates a URL for the given filename.protected booleanexceedsMaxIndividualAssetSize(long individualAssetSizeInBytes) protected booleanexceedsMaxZipFileSize(long zipSizeInBytes) protected voidextractCurrentEntryToFile(ZipInputStream zipInputStream, File extractionTarget) Reads the current zip entry's data and writes it to theextractionTarget.protected voidextractToFileAndPutInMap(String entryPath, Path tempDirectoryForExtraction, ZipInputStream zipInputStream, Map<String, File> filesByNormalizedPath) Creates a new file inside oftempDirectoryForExtraction, extracts the current zip entry's data to it viaextractCurrentEntryToFile(ZipInputStream, File), and then puts the appropriate mapping infilesByPath.extractZip(File zipFile, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) protected AssetgenerateAssetForUploadRequest(Asset assetRequest, String mimeType, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Generates a newAssetobject for an upload using the mime type and optional properties provided inassetRequest.generateAssetsForFiles(Stream<Map.Entry<String, File>> filesByNormalizedPath, Map<String, String> contextDiscriminatedUrlsByNormalizedPath, Map<String, Folder> createdFoldersByNormalizedPath, Asset assetRequest, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) protected StringgenerateContextDiscriminatedUniqueUrl(String filePath, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Given a file path, generate a unique URL with a context-discrimination prefix that's suitable for being supplied to the storage provider.protected StringgenerateContextDiscriminatedUniqueUrl(String filePath, String folderName, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Given a file path, generate a unique URL with a context-discrimination prefix that's suitable for being supplied to the storage provider.generateContextDiscriminatedUniqueUrls(Collection<String> filePaths, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Deprecated.generateContextDiscriminatedUniqueUrls(Collection<String> filePaths, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean ignoreFolderName) Given a collection of file names, generates a unique URL for each with a context-discrimination prefix that's suitable for being supplied to the storage provider.getAssetDimensions(@NonNull ResourceWithMetadata videoResource) Gets dimensions for given assetResourceWithMetadatagetAssetDimensions(@NonNull File assetFile) Gets dimensions for given asset filegetAssetDimensions(@NonNull InputStream fileInputStream) Gets dimensions for given assetInputStreamprotected AssetStorageUtilsprotected AssetUrlGenerationHelpergetFailedNormalizedFilePaths(DefaultStorageService.ZipExtractionResult zipExtractionResult, BulkAddResourcesResponse addResourcesResponse, Map<String, String> contextDiscriminatedUrlsByNormalizedPath) getImageDimensions(@NonNull ResourceWithMetadata imageResource) Deprecated, for removal: This API element is subject to removal in a future version.getImageDimensions(@NonNull File assetFile) Deprecated, for removal: This API element is subject to removal in a future version.in favor ofgetAssetDimensions(InputStream)getImageDimensions(@NonNull ImageInputStream imageInputStream) Deprecated, for removal: This API element is subject to removal in a future version.in favor ofgetAssetDimensions(InputStream)protected Stringprotected jakarta.activation.FileTypeMapprotected StringgetMimeType(String fileName) protected StringgetMimeType(org.springframework.web.multipart.MultipartFile file) protected StringgetMimeTypeNotSupportedErrorMessage(String mimeType) protected StringgetParentDirectoryPath(String normalizedPath) Gets the parent directory path from the given normalized path.protected StringgetParentFolderId(String normalizedPath, Map<String, Folder> createdFoldersByNormalizedPath, Asset assetRequest) Gets the parent directory path fromnormalizedPath, gets theFolderfor that parent directory path increatedFoldersByNormalizedPath, and returns itsFolder.getId().protected Stringprotected voidhandleExceptionWithZipFile(FileUploadState uploadState, String zipFileName, Exception e, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) protected voidhandleFailedValidationWithZipFile(FileUploadState uploadState, String zipFileName, String errorMessage, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) protected booleanisWhitelistedMimeType(String mimeType) protected booleanprotected voidmapEligibleProperties(Asset targetAsset, Asset source) Ifsourceis present, will copy itsAsset.getTags(),Asset.getFolderId()andAsset.getLocale()totargetAsset.protected booleanmatchesAnyResourceNameToIgnore(String resourceName) protected voidprocessZipExtractionResult(DefaultStorageService.ZipExtractionResult zipExtractionResult, FileUploadState uploadState, Asset assetRequest, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg) Deprecated.protected voidprocessZipExtractionResult(DefaultStorageService.ZipExtractionResult zipExtractionResult, FileUploadState uploadState, Asset assetRequest, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg, boolean ignoreFolderName) Given aDefaultStorageService.ZipExtractionResult, creates all of the necessaryFoldersin the data store, uploads the extracted files to the storage provider (after optimizing them if necessary), and createsAssetsin the data store for all successfully uploaded files.protected booleanreadEntryAndReturnIfSizeExceedsLimit(ZipInputStream zipInputStream) Reads and counts the byte size of the current entry in the zip input stream, reporting if the size exceeds theInternalAssetProperties.getMaxIndividualAssetSize().voidremoveFile(String filename) Deprecated, for removal: This API element is subject to removal in a future version.voidremoveFile(String filename, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Remove the provided file from the storage provider.voidsetAssetStorageUtils(AssetStorageUtils assetStorageUtils) protected voidsetUploadStatus(FileUploadState uploadState, BulkAddResourcesResponse bulkAddResourcesResponse) protected FilestoreFile(String url, InputStream fileInputStream, String fileName) Deprecated, for removal: This API element is subject to removal in a future version.in favor ofstoreResource(String, InputStream, String)protected FilestoreMultipartFile(String url, org.springframework.web.multipart.MultipartFile file, boolean optimizeImg) Deprecated, for removal: This API element is subject to removal in a future version.protected ResourceWithMetadatastoreMultipartFileResource(String url, org.springframework.web.multipart.MultipartFile file, boolean optimizeImg) protected ResourceWithMetadatastoreResource(String url, InputStream inputStream, String fileName) voidunzipAndUploadResourcesAsync(File sourceZipFile, String fileUploadStateId, Asset assetRequest, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg) Deprecated.voidunzipAndUploadResourcesAsync(File sourceZipFile, String fileUploadStateId, Asset assetRequest, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg, boolean ignoreFolderName) uploadResource(org.springframework.web.multipart.MultipartFile file, Asset assetRequest, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg) Uploads a single file, creating anAssetfor it (optionally using details specified inassetRequestif present).validateEntriesInZip(File sourceZipFile) Reads and validates all of the non-directory (and non-ignored) entries in the given zip file.validateEntry(ZipEntry entry, ZipInputStream zipInputStream) Reads the entry and validates its mime type and size are acceptable.validateEntryName(String filename) Validates that the filename of the Zip entry does not contain any path traversals.protected StringvalidateFileAndCreateUrl(org.springframework.web.multipart.MultipartFile file, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Validates the uploaded file and creates a URL for it.protected StringvalidateFileAndCreateUrl(org.springframework.web.multipart.MultipartFile file, String folderName, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Validates the uploaded file and creates a URL for it.protected voidvalidateIndividualAssetSize(long individualSizeInBytes) protected StringvalidateZipAndReturnErrorMessage(File sourceZipFile) Validates that the given file does not exceed theInternalAssetProperties.getMaxZipFileSize(), and validates the individual files inside as described invalidateEntriesInZip(File).protected voidvalidateZipFileSize(long zipSizeInBytes) voidvalidateZipResource(@NonNull org.springframework.web.multipart.MultipartFile file) A simple method intended to be used to pre-validate aMultipartFilereceived in an API request when expecting a zip file.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface com.broadleafcommerce.asset.service.StorageService
addAttributesToAsset
-
Field Details
-
FAILED_TO_STORE_FILE_ERROR_MESSAGE
- See Also:
-
FILE_UPLOAD_ERROR_MESSAGE
- See Also:
-
MIME_TYPE_NOT_SUPPORTED_FMT
- See Also:
-
ONLY_ZIP_SUPPORTED
- See Also:
-
ZIP_FILENAME_PATH_TRAVERSAL
- See Also:
-
assetService
-
folderService
-
multipartConfigElement
protected final jakarta.servlet.MultipartConfigElement multipartConfigElement -
storageProvider
-
internalAssetProperties
-
typeFactory
protected final com.broadleafcommerce.common.extension.TypeFactory typeFactory -
imageOperationService
-
fileUploadStateService
-
reference
protected final com.broadleafcommerce.common.extension.data.DataRouteReference reference -
assetStorageUtils
-
-
Constructor Details
-
DefaultStorageService
public DefaultStorageService(AssetService<Asset> assetService, FolderService<Folder> folderService, jakarta.servlet.MultipartConfigElement multipartConfigElement, StorageProvider storageProvider, InternalAssetProperties internalAssetProperties, com.broadleafcommerce.common.extension.TypeFactory typeFactory, ImageOperationService imageOperationService, FileUploadStateService<FileUploadState> fileUploadStateService, jakarta.activation.FileTypeMap mimeFileTypeMap, AssetUrlGenerationHelper assetUrlGenerationHelper, com.broadleafcommerce.common.extension.data.DataRouteReference reference)
-
-
Method Details
-
uploadResource
public Asset uploadResource(org.springframework.web.multipart.MultipartFile file, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg) Description copied from interface:StorageServiceUploads a single file, creating anAssetfor it (optionally using details specified inassetRequestif present).Validation includes:
- File size is within the size limits of `spring.servlet.multipart.max-file-size`
- File is of a supported mime type from `broadleaf.asset.storage.whitelisted-mime-type-formats`
- File path and name does not already exist on a asset within the system
- Specified by:
uploadResourcein interfaceStorageService- Parameters:
file- the file to be uploaded to the system.assetRequest- (optional) asset from which to derive certain attributes when creating the finalAssetfor the file. Currently,Asset.tagsandAsset.localeare used.contextInfo- context information around sandboxing and multitenant stateoptimizeImg- optimizes the image iftrue- Returns:
- the created asset after the associated resource has been uploaded
-
validateFileAndCreateUrl
protected String validateFileAndCreateUrl(org.springframework.web.multipart.MultipartFile file, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Validates the uploaded file and creates a URL for it.Intended to be overridden if there is some different validation or custom business logic required. For example, if an asset with the same URL already exists, the current implementation increments the file name with an increasing integer, like filename-1.txt. An alternate implementation may want to simply throw
FileUploadBadRequestException.- Parameters:
file- the uploaded filecontextInfo- context information surrounding sandboxing and multitenant state- Returns:
- the created url
- Throws:
org.springframework.web.multipart.MaxUploadSizeExceededException- if the file is too largeFileUploadBadRequestException- if the mime type of the file is not supportedIllegalArgumentException- if the filename is invalid
-
validateFileAndCreateUrl
protected String validateFileAndCreateUrl(org.springframework.web.multipart.MultipartFile file, @Nullable String folderName, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Validates the uploaded file and creates a URL for it.Intended to be overridden if there is some different validation or custom business logic required. For example, if an asset with the same URL already exists, the current implementation increments the file name with an increasing integer, like filename-1.txt. An alternate implementation may want to simply throw
FileUploadBadRequestException.- Parameters:
file- the uploaded filefolderName- the folder name/path for the uploaded filecontextInfo- context information surrounding sandboxing and multitenant state- Returns:
- the created url
- Throws:
org.springframework.web.multipart.MaxUploadSizeExceededException- if the file is too largeFileUploadBadRequestException- if the mime type of the file is not supportedIllegalArgumentException- if the filename is invalid
-
isWhitelistedMimeType
-
createUniqueUrlFromFilename
protected String createUniqueUrlFromFilename(String filename, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Creates a URL for the given filename. If the URL is found to be in use by another asset, it is suffixed with an incrementing integer value. For example, "/url.txt" becomes "/url-1.txt", and a subsequent creation would become "/url-2.txt".Delegates to
AssetUrlGenerationHelper.createUrl(String, String)andAssetUrlGenerationHelper.applyIncrementingSuffix(String, ContextInfo).- Parameters:
filename- the filename for which a URL should be created. Does not have to be cleaned/normalized - this method will do that.contextInfo- context information surrounding sandboxing and multitenant state- Returns:
- a unique URL for the given filename
- Throws:
IllegalArgumentException- if the filename is invalid
-
createUniqueUrlFromFilename
protected String createUniqueUrlFromFilename(String filename, @Nullable String folderName, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Creates a URL for the given filename. If the URL is found to be in use by another asset, it is suffixed with an incrementing integer value. For example, "/url.txt" becomes "/url-1.txt", and a subsequent creation would become "/url-2.txt".Delegates to
AssetUrlGenerationHelper.createUrl(String, String)andAssetUrlGenerationHelper.applyIncrementingSuffix(String, ContextInfo).- Parameters:
filename- the filename for which a URL should be created. Does not have to be cleaned/normalized - this method will do that.folderName- the folder name/path for which an asset's URL will be created withcontextInfo- context information surrounding sandboxing and multitenant state- Returns:
- a unique URL for the given filename
- Throws:
IllegalArgumentException- if the filename is invalid
-
validateIndividualAssetSize
protected void validateIndividualAssetSize(long individualSizeInBytes) -
exceedsMaxIndividualAssetSize
protected boolean exceedsMaxIndividualAssetSize(long individualAssetSizeInBytes) -
validateZipFileSize
protected void validateZipFileSize(long zipSizeInBytes) -
exceedsMaxZipFileSize
protected boolean exceedsMaxZipFileSize(long zipSizeInBytes) -
getMimeType
-
getMimeType
-
generateAssetForUploadRequest
protected Asset generateAssetForUploadRequest(@Nullable Asset assetRequest, String mimeType, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Generates a newAssetobject for an upload using the mime type and optional properties provided inassetRequest.- Parameters:
assetRequest- (optional) an asset supplied in the original request containing properties that should be copied into the newly createdAssetmimeType- the mime type of the file corresponding to this assetcontextInfo- context information surrounding sandboxing and multitenant state- Returns:
- a new
Assetobject with its fields initialized based upon the given file andassetRequest - See Also:
-
mapEligibleProperties
Ifsourceis present, will copy itsAsset.getTags(),Asset.getFolderId()andAsset.getLocale()totargetAsset.- Parameters:
targetAsset- the asset whose properties should be setsource- the asset from which properties should be derived
-
unzipAndUploadResourcesAsync
@Deprecated public void unzipAndUploadResourcesAsync(File sourceZipFile, String fileUploadStateId, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg) Deprecated.Description copied from interface:StorageServiceAsynchronously upload the individual contents of a zip file to the storage provider, and create all necessaryFoldersandAssetsin the data store for them. This method updates theFileUploadStatewith idfileUploadStateIdwith the status of upload.Certain validations are done in a way that, if not satisfied, cause the entire contents of the zip to fail to upload. These include:
- The zip file size itself is within
InternalAssetProperties.getMaxZipFileSize() - Size for every individual extracted file is within
InternalAssetProperties.getMaxIndividualAssetSize() - Every individual extracted file is of a supported mime type as checked by
StorageProvider.isWhitelistedMimeType(String).
- Specified by:
unzipAndUploadResourcesAsyncin interfaceStorageService- Parameters:
sourceZipFile- a temporary zip file whose contents should be unzipped and uploaded to the storage provider. This file itself will be deleted following this operation. If the file passes validation andInternalAssetProperties.isStoreZipFileOnProvider()is true, then a copy of the zip file will be uploaded to the provider.fileUploadStateId- the context ID of the baseFileUploadStatefor this operation. The results of this upload attempt will be updated on this entity.assetRequest- (optional) asset from which to derive certain attributes when creating the finalAssetsfor the files. Currently,Asset.tags,Asset.locale, andAsset.folderIdare used. If supplied,Asset.folderIdis used as the root folder under which all other folders/assets will be created.contextInfo- request context information around sandbox and multitenant stateoptimizeImg- whether or not to optimize the images
- The zip file size itself is within
-
unzipAndUploadResourcesAsync
@Async("uploadResourcesExecutor") public void unzipAndUploadResourcesAsync(File sourceZipFile, String fileUploadStateId, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg, boolean ignoreFolderName) Description copied from interface:StorageServiceAsynchronously upload the individual contents of a zip file to the storage provider, and create all necessaryFoldersandAssetsin the data store for them. This method updates theFileUploadStatewith idfileUploadStateIdwith the status of upload.Certain validations are done in a way that, if not satisfied, cause the entire contents of the zip to fail to upload. These include:
- The zip file size itself is within
InternalAssetProperties.getMaxZipFileSize() - Size for every individual extracted file is within
InternalAssetProperties.getMaxIndividualAssetSize() - Every individual extracted file is of a supported mime type as checked by
StorageProvider.isWhitelistedMimeType(String).
- Specified by:
unzipAndUploadResourcesAsyncin interfaceStorageService- Parameters:
sourceZipFile- a temporary zip file whose contents should be unzipped and uploaded to the storage provider. This file itself will be deleted following this operation. If the file passes validation andInternalAssetProperties.isStoreZipFileOnProvider()is true, then a copy of the zip file will be uploaded to the provider.fileUploadStateId- the context ID of the baseFileUploadStatefor this operation. The results of this upload attempt will be updated on this entity.assetRequest- (optional) asset from which to derive certain attributes when creating the finalAssetsfor the files. Currently,Asset.tags,Asset.locale, andAsset.folderIdare used. If supplied,Asset.folderIdis used as the root folder under which all other folders/assets will be created.contextInfo- request context information around sandbox and multitenant stateoptimizeImg- whether or not to optimize the imagesignoreFolderName- whether or not to include the parent folder path in the URI resolution of the files within the zip
- The zip file size itself is within
-
validateZipAndReturnErrorMessage
Validates that the given file does not exceed theInternalAssetProperties.getMaxZipFileSize(), and validates the individual files inside as described invalidateEntriesInZip(File).- Returns:
- the error message if there was a validation failure. Will be null if there was no validation failure.
- Throws:
IOException- if there was an error reading the file
-
buildErrorMessage
protected String buildErrorMessage(@NonNull @NonNull List<DefaultStorageService.ZipEntryValidationError> errors) -
validateEntriesInZip
protected List<DefaultStorageService.ZipEntryValidationError> validateEntriesInZip(File sourceZipFile) throws IOException Reads and validates all of the non-directory (and non-ignored) entries in the given zip file.- Parameters:
sourceZipFile- the zip file to read- Returns:
- a list of all validation errors that were encountered with entries. Will be empty if no errors were found.
- Throws:
IOException- if there was an error reading the file- See Also:
-
validateEntryName
@Nullable protected DefaultStorageService.ZipEntryValidationError validateEntryName(String filename) Validates that the filename of the Zip entry does not contain any path traversals.- Parameters:
filename- the file name of the Zip entry- Returns:
- the validation error if one was detected,
nullotherwise
-
validateEntry
@Nullable protected DefaultStorageService.ZipEntryValidationError validateEntry(ZipEntry entry, ZipInputStream zipInputStream) throws IOException Reads the entry and validates its mime type and size are acceptable.- Parameters:
entry- basic information about the entry itself. This entry is guaranteed not to be a directory or a resource that should be ignored.zipInputStream- a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.- Returns:
- the validation error if one was detected,
nullotherwise - Throws:
IOException- if there was an error reading the file
-
readEntryAndReturnIfSizeExceedsLimit
protected boolean readEntryAndReturnIfSizeExceedsLimit(ZipInputStream zipInputStream) throws IOException Reads and counts the byte size of the current entry in the zip input stream, reporting if the size exceeds theInternalAssetProperties.getMaxIndividualAssetSize().- Parameters:
zipInputStream- a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.- Returns:
- true if the entry's size exceeds the maximum limit, false otherwise
- Throws:
IOException- if there was an error reading the file
-
getIndividualAssetTooLargeErrorMessage
-
getZipTooLargeErrorMessage
-
getMimeTypeNotSupportedErrorMessage
-
setUploadStatus
protected void setUploadStatus(FileUploadState uploadState, BulkAddResourcesResponse bulkAddResourcesResponse) -
handleExceptionWithZipFile
protected void handleExceptionWithZipFile(FileUploadState uploadState, String zipFileName, Exception e, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) -
handleFailedValidationWithZipFile
protected void handleFailedValidationWithZipFile(FileUploadState uploadState, String zipFileName, String errorMessage, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) -
validateZipResource
public void validateZipResource(@NonNull @NonNull org.springframework.web.multipart.MultipartFile file) Description copied from interface:StorageServiceA simple method intended to be used to pre-validate aMultipartFilereceived in an API request when expecting a zip file.While methods like
StorageService.unzipAndUploadResourcesAsync(File, String, Asset, ContextInfo, boolean)do perform certain validations, this method is intended to allow immediate rejection of invalid requests before getting too far in the flow.Default validations:
- File has an `application/zip` mime type.
- File size is within
InternalAssetProperties.getMaxZipFileSize()
- Specified by:
validateZipResourcein interfaceStorageService- Parameters:
file- the file to validate
-
isZipType
-
processZipExtractionResult
@Deprecated protected void processZipExtractionResult(DefaultStorageService.ZipExtractionResult zipExtractionResult, FileUploadState uploadState, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg) Deprecated.Given aDefaultStorageService.ZipExtractionResult, creates all of the necessaryFoldersin the data store, uploads the extracted files to the storage provider (after optimizing them if necessary), and createsAssetsin the data store for all successfully uploaded files.The
FileUploadStatewill be updated in the data store to reflect the final status of the operation.This method guarantees that the
DefaultStorageService.ZipExtractionResult.temporaryDirectoryFilesWereExtractedToand all of its contents will be deleted regardless of success or failure.- Parameters:
zipExtractionResult- an object containing the results of extracting a zip fileuploadState- theFileUploadStatefrom the data store corresponding to this zip upload/extract operation. Will be updated and sent to the data store with the final status of this operation.assetRequest- (optional) the caller-requested asset details from which to derive certain attributes when creating the final assets/folders for the filescontextInfo- request context information around multitenant stateoptimizeImg- iftrue, the extracted files will be optimized before being uploaded to the storage provider
-
processZipExtractionResult
protected void processZipExtractionResult(DefaultStorageService.ZipExtractionResult zipExtractionResult, FileUploadState uploadState, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg, boolean ignoreFolderName) Given aDefaultStorageService.ZipExtractionResult, creates all of the necessaryFoldersin the data store, uploads the extracted files to the storage provider (after optimizing them if necessary), and createsAssetsin the data store for all successfully uploaded files.The
FileUploadStatewill be updated in the data store to reflect the final status of the operation.This method guarantees that the
DefaultStorageService.ZipExtractionResult.temporaryDirectoryFilesWereExtractedToand all of its contents will be deleted regardless of success or failure.- Parameters:
zipExtractionResult- an object containing the results of extracting a zip fileuploadState- theFileUploadStatefrom the data store corresponding to this zip upload/extract operation. Will be updated and sent to the data store with the final status of this operation.assetRequest- (optional) the caller-requested asset details from which to derive certain attributes when creating the final assets/folders for the filescontextInfo- request context information around multitenant stateoptimizeImg- iftrue, the extracted files will be optimized before being uploaded to the storage providerignoreFolderName- iftrue, the extracted files' URIs will not contain their parent folder paths
-
createAllFolders
protected Map<String,Folder> createAllFolders(Map<String, Folder> foldersToCreateByNormalizedPath, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, @Nullable Asset assetRequest) Creates all of the givenFoldersin the data store, and returns the created items.This method sets the
Folder.getParentFolderId()on each folder as determined by the directory paths to mimic the same hierarchy. For top-level folders whose directory paths have no parent, theFolder.getParentFolderId()will either benullorAsset.getFolderId()if provided in theassetRequest.- Parameters:
foldersToCreateByNormalizedPath- the map of normalized directory paths toFolderobjects that should be createdcontextInfo- context information surrounding multitenant stateassetRequest- the caller-requested asset details- Returns:
- a map from normalized folder names to created
Folderobjects
-
getParentFolderId
@Nullable protected String getParentFolderId(String normalizedPath, Map<String, Folder> createdFoldersByNormalizedPath, @Nullable Asset assetRequest) Gets the parent directory path fromnormalizedPath, gets theFolderfor that parent directory path increatedFoldersByNormalizedPath, and returns itsFolder.getId().Alternatively, if this path does not have a parent directory and
assetRequestwas supplied, theAsset.getFolderId()from the request will be used instead. This way any "root level" items will have that folder ID as their parent.- Parameters:
normalizedPath- the normalized path of the directory or file whose parent folder needs to be determinedcreatedFoldersByNormalizedPath- a map from normalized directory names to createdFolders. Used to find the correspondingFolderfor the parent directory path.assetRequest- the caller-requested asset details- Returns:
- the
Folder.getId()of theFolderfor the parent directory, ornullif this item does not have a parent directory
-
getParentDirectoryPath
Gets the parent directory path from the given normalized path.- Parameters:
normalizedPath- the normalized path of a file or directory. For example, "directory/" or "directory" or "directory/file.txt".- Returns:
- the path for this path's parent directory, or
nullif this path does not have a parent
-
batchOptimizeFiles
Delegates toImageOperationServiceto optimize the given files as a batch. The optimization will write over the given files.- Parameters:
filesToOptimizeByNormalizedPath- a map of normalized file paths to file objects
-
generateContextDiscriminatedUniqueUrls
@Deprecated protected Map<String,String> generateContextDiscriminatedUniqueUrls(Collection<String> filePaths, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Deprecated.Given a collection of file names, generates a unique URL for each with a context-discrimination prefix that's suitable for being supplied to the storage provider.- Parameters:
filePaths- file names for which context discriminated unique URLs need to be created. Do not have to be cleaned/normalized - this method will do that.contextInfo- context information surrounding sandboxing and multitenant state- Returns:
- mappings from given file names to the unique urls that were generated for them
-
generateContextDiscriminatedUniqueUrls
protected Map<String,String> generateContextDiscriminatedUniqueUrls(Collection<String> filePaths, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean ignoreFolderName) Given a collection of file names, generates a unique URL for each with a context-discrimination prefix that's suitable for being supplied to the storage provider.- Parameters:
filePaths- file names for which context discriminated unique URLs need to be created. Do not have to be cleaned/normalized - this method will do that.contextInfo- context information surrounding sandboxing and multitenant stateignoreFolderName- iftrue, the generated URIs for the given file paths will not include their parent folder paths- Returns:
- mappings from given file names to the unique urls that were generated for them
-
generateContextDiscriminatedUniqueUrl
protected String generateContextDiscriminatedUniqueUrl(String filePath, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Given a file path, generate a unique URL with a context-discrimination prefix that's suitable for being supplied to the storage provider.- Parameters:
filePath- a file name for which a context discriminated unique URL needs to be created. Does not have to be cleaned/normalized - this method will do that.contextInfo- context information surrounding sandboxing and multitenant state- Returns:
- a unique context discriminated URL that was generated for the given path
-
generateContextDiscriminatedUniqueUrl
protected String generateContextDiscriminatedUniqueUrl(String filePath, @Nullable String folderName, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Given a file path, generate a unique URL with a context-discrimination prefix that's suitable for being supplied to the storage provider.- Parameters:
filePath- a file name for which a context discriminated unique URL needs to be created. Does not have to be cleaned/normalized - this method will do that.folderName- the folder name/path of the file used to create the unique URLcontextInfo- context information surrounding sandboxing and multitenant state- Returns:
- a unique context discriminated URL that was generated for the given path
-
createAssetsForSuccessfullyUploadedFiles
protected List<Asset> createAssetsForSuccessfullyUploadedFiles(DefaultStorageService.ZipExtractionResult zipExtractionResult, Map<String, String> contextDiscriminatedUrlsByNormalizedPath, Map<String, Folder> createdFoldersByNormalizedPath, BulkAddResourcesResponse addResourcesResponse, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) CreatesAssetsin the data store for the files that were successfully uploaded to the storage provider. This method takesBulkAddResourcesResponse.getGivenFilenamesToSuccessfullyCreatedPaths(), maps those back to the originally extracted files fromDefaultStorageService.ZipExtractionResult.getFilesByNormalizedPath(), and then builds/inserts the assets in the data store.- Parameters:
zipExtractionResult- an object containing the results of extracting the original zip filecontextDiscriminatedUrlsByNormalizedPath- mappings from the original normalized path names of files to the unique urls that were generated for them. Keys should correspond to keys inDefaultStorageService.ZipExtractionResult.getFilesByNormalizedPath(), and values should correspond to keys inBulkAddResourcesResponse.getGivenFilenamesToSuccessfullyCreatedPaths().createdFoldersByNormalizedPath- a map from normalized directory names to createdFolders. Used to find the correspondingFolderfor the parent directory path of a file's normalized path.addResourcesResponse- the response returned by the storage provider describing which file uploads succeeded and which failedassetRequest- (optional) the caller-requested asset details from which to derive certain attributes when creating the final assets for the files.contextInfo- context information surrounding multitenant state- Returns:
- the list of all assets that were created in the data store. Will not be null, but may be empty if there were no successfully uploaded files.
-
generateAssetsForFiles
protected List<Asset> generateAssetsForFiles(Stream<Map.Entry<String, File>> filesByNormalizedPath, Map<String, String> contextDiscriminatedUrlsByNormalizedPath, Map<String, Folder> createdFoldersByNormalizedPath, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) -
getFailedNormalizedFilePaths
protected Set<String> getFailedNormalizedFilePaths(DefaultStorageService.ZipExtractionResult zipExtractionResult, BulkAddResourcesResponse addResourcesResponse, Map<String, String> contextDiscriminatedUrlsByNormalizedPath) -
storeMultipartFile
@Deprecated(since="2.0.1", forRemoval=true) protected File storeMultipartFile(String url, org.springframework.web.multipart.MultipartFile file, boolean optimizeImg) Deprecated, for removal: This API element is subject to removal in a future version. -
storeMultipartFileResource
protected ResourceWithMetadata storeMultipartFileResource(String url, org.springframework.web.multipart.MultipartFile file, boolean optimizeImg) -
storeFile
@Deprecated(since="2.0.1", forRemoval=true) protected File storeFile(String url, InputStream fileInputStream, String fileName) Deprecated, for removal: This API element is subject to removal in a future version.in favor ofstoreResource(String, InputStream, String) -
storeResource
-
removeFile
Deprecated, for removal: This API element is subject to removal in a future version.Description copied from interface:StorageServiceRemove the provided file from the storage provider.- Specified by:
removeFilein interfaceStorageService- Parameters:
filename- the name of the file to delete on the storage provider
-
removeFile
public void removeFile(String filename, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Description copied from interface:StorageServiceRemove the provided file from the storage provider.- Specified by:
removeFilein interfaceStorageService- Parameters:
filename- the name of the file to delete on the storage providercontextInfo- context of the request: information around sandbox and multitenant state
-
extractZip
protected DefaultStorageService.ZipExtractionResult extractZip(File zipFile, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) throws IOException Extracts the contents of the zip file to a temporary directory, building anyFolderobjects for directories and creating temporaryfilesfor extracted files.This method guarantees that the temporary extraction directory and its contents will be wiped if an error is encountered.
- Parameters:
zipFile- The zip file to extractcontextInfo- context information surrounding multitenant state- Returns:
- details about the extracted folders and files
- Throws:
IOException- if there was an IO problem extracting the file.
-
matchesAnyResourceNameToIgnore
-
buildFolderAndPutInMap
protected void buildFolderAndPutInMap(String directoryPath, Map<String, Folder> foldersByNormalizedPath, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) Given a directory path that was found in a zip file, build aFolderfor it and put it in the givenfoldersByPathmap.The path of the directory is first cleaned and normalized. This is used as the key for
foldersByPath.The last segment of the normalized path is then set as the
Folder.getName().This method does not initialize
Folder.getParentFolderId(), as that is done in a later step increateAllFolders(Map, ContextInfo, Asset)when the entities are created.- Parameters:
directoryPath- the full name of the directory (with path information) as found in the zip entryfoldersByNormalizedPath- a map of normalized folder names toFolderobjects (as described inDefaultStorageService.ZipExtractionResult.getFoldersByNormalizedPath()) which the new folder should be placed incontextInfo- context information surrounding multitenant state
-
extractToFileAndPutInMap
protected void extractToFileAndPutInMap(String entryPath, Path tempDirectoryForExtraction, ZipInputStream zipInputStream, Map<String, File> filesByNormalizedPath) throws IOExceptionCreates a new file inside oftempDirectoryForExtraction, extracts the current zip entry's data to it viaextractCurrentEntryToFile(ZipInputStream, File), and then puts the appropriate mapping infilesByPath.The path of the zip entry is first cleaned and normalized, and then used as the key for
filesByPath.- Parameters:
entryPath- the original name of the zip entrytempDirectoryForExtraction- the temporary directory in which to write the extracted filezipInputStream- a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.filesByNormalizedPath- a map of normalized file names toFileobjects (as described inDefaultStorageService.ZipExtractionResult.getFilesByNormalizedPath()) which the extracted file should be placed in- Throws:
IOException- if there was an error reading/writing data
-
extractCurrentEntryToFile
protected void extractCurrentEntryToFile(ZipInputStream zipInputStream, File extractionTarget) throws IOException Reads the current zip entry's data and writes it to theextractionTarget.- Parameters:
zipInputStream- a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.extractionTarget- the file to which the zip entry's data should be written- Throws:
IOException- if there was an error reading/writing the data
-
addAttributesToAsset
Responsible for adding any attributes to the asset that are derived from the uploaded file.- Specified by:
addAttributesToAssetin interfaceStorageService- Parameters:
asset- the asset to which to add attributesfile- the file from which to derive attributes
-
addImageAttributes
-
addAttributesToAsset
public void addAttributesToAsset(@NonNull @NonNull Asset asset, @NonNull @NonNull ResourceWithMetadata resource) Responsible for adding any attributes to the asset that are derived from the uploadedResource.- Specified by:
addAttributesToAssetin interfaceStorageService- Parameters:
asset- the asset to which to add attributesresource- theResourceWithMetadatafrom which to derive attributes
-
getAssetDimensions
Gets dimensions for given asset file- Parameters:
assetFile- asset file- Returns:
- dimensions of the asset, null if no dimensions found
- Since:
- 2.1.3
-
getAssetDimensions
protected Optional<Dimension> getAssetDimensions(@NonNull @NonNull ResourceWithMetadata videoResource) Gets dimensions for given assetResourceWithMetadata- Parameters:
videoResource- an assetResourceWithMetadata- Returns:
- dimensions of the asset or
Optional.empty()if no dimensions found - Since:
- 2.1.3
-
getImageDimensions
@Deprecated(since="2.1.3", forRemoval=true) protected Optional<Dimension> getImageDimensions(@NonNull @NonNull File assetFile) Deprecated, for removal: This API element is subject to removal in a future version.in favor ofgetAssetDimensions(InputStream)Gets image dimensions for given asset file- Parameters:
assetFile- asset file- Returns:
- dimensions of image, null if not an image
-
getImageDimensions
@Deprecated(since="2.1.3", forRemoval=true) protected Optional<Dimension> getImageDimensions(@NonNull @NonNull ResourceWithMetadata imageResource) Deprecated, for removal: This API element is subject to removal in a future version.in favor ofgetAssetDimensions(ResourceWithMetadata)Gets image dimensions for given assetResourceWithMetadata- Parameters:
imageResource- an assetResourceWithMetadata- Returns:
- dimensions of image or
Optional.empty()if not an image
-
getImageDimensions
@Deprecated(since="2.1.3", forRemoval=true) protected Optional<Dimension> getImageDimensions(@NonNull @NonNull ImageInputStream imageInputStream) Deprecated, for removal: This API element is subject to removal in a future version.in favor ofgetAssetDimensions(InputStream)Gets image dimensions for given assetImageInputStream- Parameters:
imageInputStream- an assetImageInputStream- Returns:
- dimensions of image or
Optional.empty()if not an image
-
getAssetDimensions
Gets dimensions for given assetInputStream- Parameters:
fileInputStream- an assetInputStream- Returns:
- dimensions of the asset or
Optional.empty()if no dimensions found - Since:
- 2.1.3
-
getMimeFileTypeMap
@NonNull protected jakarta.activation.FileTypeMap getMimeFileTypeMap() -
getAssetUrlGenerationHelper
-
getAssetStorageUtils
-
setAssetStorageUtils
-
getAssetDimensions(ResourceWithMetadata)