diff --git a/src/main/java/dev/vality/file/storage/handler/FileStorageHandler.java b/src/main/java/dev/vality/file/storage/handler/FileStorageHandler.java index 7a971fc..4d197d3 100644 --- a/src/main/java/dev/vality/file/storage/handler/FileStorageHandler.java +++ b/src/main/java/dev/vality/file/storage/handler/FileStorageHandler.java @@ -51,7 +51,11 @@ public class FileStorageHandler implements FileStorageSrv.Iface { } } + /** + * @deprecated This method will be remove in next version. + */ @Override + @Deprecated(forRemoval = true) public FileData getMultipartFileData(String fileDataId) throws TException { try { log.info("Receive request for get multipart file data with fileDataId={}", fileDataId); @@ -92,7 +96,11 @@ public class FileStorageHandler implements FileStorageSrv.Iface { return result; } + /** + * @deprecated This method will be remove in next version. + */ @Override + @Deprecated(forRemoval = true) public String generateMultipartDownloadUrl(String fileDataId, String expiresAt) throws TException { try { log.info("Receive request for generate download url with fileDataId={}", fileDataId); diff --git a/src/main/java/dev/vality/file/storage/service/S3V2Service.java b/src/main/java/dev/vality/file/storage/service/S3V2Service.java index 3a1e80c..4ef6aae 100644 --- a/src/main/java/dev/vality/file/storage/service/S3V2Service.java +++ b/src/main/java/dev/vality/file/storage/service/S3V2Service.java @@ -25,6 +25,8 @@ import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignReques import javax.annotation.PostConstruct; import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.Instant; import java.util.*; @@ -201,10 +203,7 @@ public class S3V2Service implements StorageService { private void uploadFileMetadata(Map metadata, String fileId) { try { - var s3Metadata = new HashMap(); - s3Metadata.put(FILE_ID, fileId); - s3Metadata.put(CREATED_AT, Instant.now().toString()); - metadata.forEach((key, value) -> s3Metadata.put(METADATA + key, DamselUtil.toJsonString(value))); + HashMap s3Metadata = buildS3Metadata(metadata, fileId); var request = PutObjectRequest.builder() .bucket(s3SdkV2Properties.getBucketName()) .key(fileId) @@ -395,16 +394,19 @@ public class S3V2Service implements StorageService { @Override public CreateMultipartUploadResult createMultipartUpload(Map metadata) { + if (!metadata.containsKey(FILENAME_METADATA)) { + throw new StorageException("Can't create multipart upload object without fileName"); + } var fileId = UUID.randomUUID().toString(); + uploadFileMetadata(metadata, fileId); try { - var s3Metadata = new HashMap(); - s3Metadata.put(FILE_ID, fileId); - s3Metadata.put(CREATED_AT, Instant.now().toString()); - metadata.forEach((key, value) -> s3Metadata.put(METADATA + key, DamselUtil.toJsonString(value))); + HashMap s3Metadata = buildS3Metadata(metadata, fileId); + String filename = URLEncoder.encode(metadata.get(FILENAME_METADATA).getStr(), StandardCharsets.UTF_8); var createRequest = CreateMultipartUploadRequest.builder() .bucket(s3SdkV2Properties.getBucketName()) .key(fileId) .metadata(s3Metadata) + .contentDisposition("attachment;filename=" + filename) .build(); CreateMultipartUploadResponse createResponse = s3SdkV2Client.createMultipartUpload(createRequest); var response = createResponse.sdkHttpResponse(); @@ -429,6 +431,14 @@ public class S3V2Service implements StorageService { } } + private static HashMap buildS3Metadata(Map metadata, String fileId) { + var s3Metadata = new HashMap(); + s3Metadata.put(FILE_ID, fileId); + s3Metadata.put(CREATED_AT, Instant.now().toString()); + metadata.forEach((key, value) -> s3Metadata.put(METADATA + key, DamselUtil.toJsonString(value))); + return s3Metadata; + } + @Override public UploadMultipartResult uploadMultipart(UploadMultipartRequestData requestData) { String fileId = requestData.getFileDataId(); diff --git a/src/test/java/dev/vality/file/storage/FileStorageTest.java b/src/test/java/dev/vality/file/storage/FileStorageTest.java index b7c4278..387b785 100644 --- a/src/test/java/dev/vality/file/storage/FileStorageTest.java +++ b/src/test/java/dev/vality/file/storage/FileStorageTest.java @@ -1,5 +1,7 @@ package dev.vality.file.storage; +import dev.vality.file.storage.service.exception.StorageException; +import dev.vality.woody.api.flow.error.WRuntimeException; import dev.vality.woody.thrift.impl.http.THSpawnClientBuilder; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; @@ -35,6 +37,8 @@ import java.util.concurrent.Executors; import static dev.vality.msgpack.Value.*; import static dev.vality.testcontainers.annotations.util.ValuesGenerator.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.*; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -347,7 +351,15 @@ public abstract class FileStorageTest { @Test public void multipartUploadTest() throws Exception { - CreateMultipartUploadResult createResult = fileStorageClient.createMultipartUpload(Collections.emptyMap()); + var exception = assertThrows(WRuntimeException.class, + () -> fileStorageClient.createMultipartUpload(Collections.emptyMap())); + assertThat(exception.getErrorDefinition().getErrorReason(), + containsString("Can't create multipart upload object without fileName")); + + + dev.vality.msgpack.Value fileName = str("fileName"); + var metadata = Map.of("filename", fileName); + CreateMultipartUploadResult createResult = fileStorageClient.createMultipartUpload(metadata); assertNotNull(createResult.getFileDataId()); assertNotNull(createResult.getMultipartUploadId()); @@ -419,7 +431,7 @@ public abstract class FileStorageTest { CompleteMultipartUploadResult result = fileStorageClient.completeMultipartUpload(completeRequest); - FileData multipartFileData = fileStorageClient.getMultipartFileData(createResult.getFileDataId()); + FileData multipartFileData = fileStorageClient.getFileData(createResult.getFileDataId()); assertEquals(createResult.getFileDataId(), multipartFileData.getFileDataId()); assertEquals(fileName, multipartFileData.getFileName()); @@ -448,7 +460,7 @@ public abstract class FileStorageTest { fileStorageClient.completeMultipartUpload(completeRequest); String expiredTime = Instant.now().toString(); - String url = fileStorageClient.generateMultipartDownloadUrl(createResult.getFileDataId(), expiredTime); + String url = fileStorageClient.generateDownloadUrl(createResult.getFileDataId(), expiredTime); assertNotNull(url); }