11package com .microsoft .migration .assets .service ;
22
3- import com .azure .identity .DefaultAzureCredentialBuilder ;
4- import com .azure .storage .blob .BlobServiceClient ;
5- import com .azure .storage .blob .BlobServiceClientBuilder ;
6- import com .azure .storage .blob .models .BlobHttpHeaders ;
7- import com .azure .storage .blob .models .BlobItem ;
8- import com .azure .storage .blob .options .BlobParallelUploadOptions ;
93import com .microsoft .migration .assets .model .ImageMetadata ;
104import com .microsoft .migration .assets .model .ImageProcessingMessage ;
115import com .microsoft .migration .assets .model .S3StorageItem ;
126import com .microsoft .migration .assets .repository .ImageMetadataRepository ;
137import lombok .RequiredArgsConstructor ;
14- import com .azure .spring .messaging .servicebus .core .ServiceBusTemplate ;
15- import org .springframework .messaging .support .MessageBuilder ;
8+ import org .springframework .amqp .rabbit .core .RabbitTemplate ;
169import org .springframework .beans .factory .annotation .Value ;
1710import org .springframework .context .annotation .Profile ;
1811import org .springframework .stereotype .Service ;
1912import org .springframework .web .multipart .MultipartFile ;
13+ import software .amazon .awssdk .core .sync .RequestBody ;
14+ import software .amazon .awssdk .services .s3 .S3Client ;
15+ import software .amazon .awssdk .services .s3 .model .*;
2016
2117import java .io .IOException ;
2218import java .io .InputStream ;
3228@ Profile ("!dev" ) // Active when not in dev profile
3329public class AwsS3Service implements StorageService {
3430
35- private final BlobServiceClient blobServiceClient ;
36- private final ServiceBusTemplate serviceBusTemplate ;
31+ private final S3Client s3Client ;
32+ private final RabbitTemplate rabbitTemplate ;
3733 private final ImageMetadataRepository imageMetadataRepository ;
3834
39- @ Value ("${azure.storage.blob.container-name }" )
40- private String containerName ;
35+ @ Value ("${aws.s3.bucket }" )
36+ private String bucketName ;
4137
4238 @ Override
4339 public List <S3StorageItem > listObjects () {
44- return blobServiceClient .getBlobContainerClient (containerName ).listBlobs ().stream ()
45- .map (blobItem -> {
40+ ListObjectsV2Request request = ListObjectsV2Request .builder ()
41+ .bucket (bucketName )
42+ .build ();
43+
44+ ListObjectsV2Response response = s3Client .listObjectsV2 (request );
45+
46+ return response .contents ().stream ()
47+ .map (s3Object -> {
4648 // Try to get metadata for upload time
4749 Instant uploadedAt = imageMetadataRepository .findAll ().stream ()
48- .filter (metadata -> metadata .getS3Key ().equals (blobItem . getName ()))
50+ .filter (metadata -> metadata .getS3Key ().equals (s3Object . key ()))
4951 .map (metadata -> metadata .getUploadedAt ().atZone (java .time .ZoneId .systemDefault ()).toInstant ())
5052 .findFirst ()
51- .orElse (blobItem . getProperties (). getLastModified (). toInstant ()); // fallback to lastModified if metadata not found
53+ .orElse (s3Object . lastModified ()); // fallback to lastModified if metadata not found
5254
5355 return new S3StorageItem (
54- blobItem . getName (),
55- extractFilename (blobItem . getName ()),
56- blobItem . getProperties (). getContentLength (),
57- blobItem . getProperties (). getLastModified (). toInstant (),
56+ s3Object . key (),
57+ extractFilename (s3Object . key ()),
58+ s3Object . size (),
59+ s3Object . lastModified (),
5860 uploadedAt ,
59- generateUrl (blobItem . getName ())
61+ generateUrl (s3Object . key ())
6062 );
6163 })
6264 .collect (Collectors .toList ());
@@ -65,11 +67,13 @@ public List<S3StorageItem> listObjects() {
6567 @ Override
6668 public void uploadObject (MultipartFile file ) throws IOException {
6769 String key = generateKey (file .getOriginalFilename ());
68-
69- var blobClient = blobServiceClient .getBlobContainerClient (containerName ).getBlobClient (key );
70- BlobHttpHeaders headers = new BlobHttpHeaders ().setContentType (file .getContentType ());
71- BlobParallelUploadOptions options = new BlobParallelUploadOptions (file .getInputStream ()).setHeaders (headers );
72- blobClient .uploadWithResponse (options , null , null );
70+ PutObjectRequest request = PutObjectRequest .builder ()
71+ .bucket (bucketName )
72+ .key (key )
73+ .contentType (file .getContentType ())
74+ .build ();
75+
76+ s3Client .putObject (request , RequestBody .fromInputStream (file .getInputStream (), file .getSize ()));
7377
7478 // Send message to queue for thumbnail generation
7579 ImageProcessingMessage message = new ImageProcessingMessage (
@@ -78,7 +82,7 @@ public void uploadObject(MultipartFile file) throws IOException {
7882 getStorageType (),
7983 file .getSize ()
8084 );
81- serviceBusTemplate . send (IMAGE_PROCESSING_QUEUE , MessageBuilder . withPayload ( message ). build () );
85+ rabbitTemplate . convertAndSend (IMAGE_PROCESSING_QUEUE , message );
8286
8387 // Create and save metadata to database
8488 ImageMetadata metadata = new ImageMetadata ();
@@ -94,23 +98,31 @@ public void uploadObject(MultipartFile file) throws IOException {
9498
9599 @ Override
96100 public InputStream getObject (String key ) throws IOException {
97- return blobServiceClient .getBlobContainerClient (containerName )
98- .getBlobClient (key )
99- .openInputStream ();
101+ GetObjectRequest request = GetObjectRequest .builder ()
102+ .bucket (bucketName )
103+ .key (key )
104+ .build ();
105+
106+ return s3Client .getObject (request );
100107 }
101108
102109 @ Override
103110 public void deleteObject (String key ) throws IOException {
104111 // Delete both original and thumbnail if it exists
105- blobServiceClient .getBlobContainerClient (containerName )
106- .getBlobClient (key )
107- .delete ();
112+ DeleteObjectRequest request = DeleteObjectRequest .builder ()
113+ .bucket (bucketName )
114+ .key (key )
115+ .build ();
116+
117+ s3Client .deleteObject (request );
108118
109119 try {
110120 // Try to delete thumbnail if it exists
111- blobServiceClient .getBlobContainerClient (containerName )
112- .getBlobClient (getThumbnailKey (key ))
113- .delete ();
121+ DeleteObjectRequest thumbnailRequest = DeleteObjectRequest .builder ()
122+ .bucket (bucketName )
123+ .key (getThumbnailKey (key ))
124+ .build ();
125+ s3Client .deleteObject (thumbnailRequest );
114126 } catch (Exception e ) {
115127 // Ignore if thumbnail doesn't exist
116128 }
@@ -124,7 +136,7 @@ public void deleteObject(String key) throws IOException {
124136
125137 @ Override
126138 public String getStorageType () {
127- return "azure " ;
139+ return "s3 " ;
128140 }
129141
130142 private String extractFilename (String key ) {
@@ -134,9 +146,11 @@ private String extractFilename(String key) {
134146 }
135147
136148 private String generateUrl (String key ) {
137- return blobServiceClient .getBlobContainerClient (containerName )
138- .getBlobClient (key )
139- .getBlobUrl ();
149+ GetUrlRequest request = GetUrlRequest .builder ()
150+ .bucket (bucketName )
151+ .key (key )
152+ .build ();
153+ return s3Client .utilities ().getUrl (request ).toString ();
140154 }
141155
142156 private String generateKey (String filename ) {
0 commit comments