Публичная папка в s3

Здравствуйте. у нас есть s3 хранилище для файлов. В этом хранилище есть папка public, файлы в ней доступны всем без авторизации. По дефолту мы хотим чтоб все файлы грузились не в эту папку. Но в определенных случаях нужно грузить в публичную папку. Можете подсказать можно что сделать в аддоне? Или нужно будет свою логику полностью писать для конкретных файловых полей?

В общем удалось так.
Отнаследовался от AwsFileStorage переопределил createFileKey чтоб тот добавлял в начале название папки public и переопределил saveStream чтоб в запросах s3Client добавить .acl(ObjectCannedACL.PUBLIC_READ)

@Component("PublicAwsFileStorage")
class PublicAwsFileStorage: AwsFileStorage(DEFAULT_STORAGE_NAME) {
    private val log: Logger = LoggerFactory.getLogger(PublicAwsFileStorage::class.java)

    /**
     * copied from [AwsFileStorage#saveStream] with addition of PUBLIC_READ ACL
     */
    override fun saveStream(fileName: String, inputStream: InputStream, parameters: Map<String, Any>): FileRef {
        val fileKey = createFileKey(fileName)
        val bucket = this.bucket
        val s3ChunkSizeBytes = this.chunkSize * 1024

        val fileRefParameters = Maps.toMap(parameters.keys) { key -> parameters[key].toString() }
        val fileRef = FileRef(getStorageName(), fileKey, fileName, fileRefParameters)

        try {
            BufferedInputStream(inputStream, s3ChunkSizeBytes).use { bos ->
                val chunkBytes = ByteArray(s3ChunkSizeBytes)
                var nBytes = bos.read(chunkBytes)
                val s3Client = s3ClientReference.get()
                if (nBytes < s3ChunkSizeBytes) {
                    s3Client.putObject({ objectBuilder: PutObjectRequest.Builder ->
                        objectBuilder
                            .bucket(bucket)
                            .key(fileKey)
                            .acl(ObjectCannedACL.PUBLIC_READ)
                            .build()
                    }, fromBytes(chunkBytes, nBytes))
                    return fileRef
                }

                val response = s3Client.createMultipartUpload { uploadBuilder ->
                    uploadBuilder
                        .bucket(bucket)
                        .key(fileKey)
                        .acl(ObjectCannedACL.PUBLIC_READ)
                }

                val completedParts = mutableListOf<CompletedPart>()
                val partBuilder = UploadPartRequest.builder()
                    .bucket(bucket)
                    .key(fileKey)
                    .uploadId(response.uploadId())
                var partNumber = 1
                while (0 < nBytes) {
                    val partResponse = s3Client.uploadPart(
                        partBuilder
                            .partNumber(partNumber)
                            .build(), fromBytes(chunkBytes, nBytes)
                    )
                    val completedPart = CompletedPart.builder()
                        .partNumber(partNumber)
                        .eTag(partResponse.eTag())
                        .build()
                    completedParts.add(completedPart)
                    nBytes = bos.read(chunkBytes)
                    partNumber++
                }

                s3Client.completeMultipartUpload { completeBuilder ->
                    completeBuilder
                        .bucket(bucket)
                        .key(fileKey)
                        .uploadId(response.uploadId())
                        .multipartUpload { multipartBuilder ->
                            multipartBuilder.parts(completedParts)
                        }
                }
                return fileRef
            }
        } catch (e: IOException) {
            log.error("Error saving file to S3 storage", e)
            val message = String.format("Could not save file %s.", fileName)
            throw FileStorageException(FileStorageException.Type.IO_EXCEPTION, message)
        } catch (e: SdkException) {
            log.error("Error saving file to S3 storage", e)
            val message = String.format("Could not save file %s.", fileName)
            throw FileStorageException(FileStorageException.Type.IO_EXCEPTION, message)
        }
    }

    override fun createFileKey(fileName: String): String {
        return "public/" + super.createFileKey(fileName)
    }

    companion object {
        const val DEFAULT_STORAGE_NAME = "publicS3"
    }

}

В Редакторах у поля fileStorageUploadField указываю fileStorageName="publicS3"

В пропертях указал jmix.core.default-file-storage=s3

Вроде бы все работает.

2 симпатии