make multipart upload like a standard flow (#23)

* make multipart upload like a standard flow

* add deprecated

* add deprecated (2)

---------

Co-authored-by: ggmaleva <ggmaleva@yandex.ru>
This commit is contained in:
Gregory 2024-02-06 18:00:48 +03:00 committed by GitHub
parent 769c158620
commit 0e38cdfaf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 11 deletions

View File

@ -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);

View File

@ -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<String, Value> metadata, String fileId) {
try {
var s3Metadata = new HashMap<String, String>();
s3Metadata.put(FILE_ID, fileId);
s3Metadata.put(CREATED_AT, Instant.now().toString());
metadata.forEach((key, value) -> s3Metadata.put(METADATA + key, DamselUtil.toJsonString(value)));
HashMap<String, String> 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<String, Value> 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<String, String>();
s3Metadata.put(FILE_ID, fileId);
s3Metadata.put(CREATED_AT, Instant.now().toString());
metadata.forEach((key, value) -> s3Metadata.put(METADATA + key, DamselUtil.toJsonString(value)));
HashMap<String, String> 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<String, String> buildS3Metadata(Map<String, Value> metadata, String fileId) {
var s3Metadata = new HashMap<String, String>();
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();

View File

@ -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);
}