15
15
16
16
package software .amazon .awssdk .services .s3 .multipart ;
17
17
18
+ import static java .util .Base64 .getEncoder ;
18
19
import static java .util .concurrent .TimeUnit .SECONDS ;
19
20
import static org .assertj .core .api .Assertions .assertThat ;
21
+ import static org .junit .Assert .assertEquals ;
20
22
import static software .amazon .awssdk .services .s3 .model .ServerSideEncryption .AES256 ;
21
23
import static software .amazon .awssdk .testutils .service .S3BucketUtils .temporaryBucketName ;
22
24
25
27
import java .io .File ;
26
28
import java .io .FileInputStream ;
27
29
import java .io .IOException ;
30
+ import java .io .InputStream ;
31
+ import java .io .OutputStream ;
28
32
import java .nio .ByteBuffer ;
29
33
import java .nio .charset .Charset ;
30
34
import java .nio .file .Files ;
35
+ import java .security .DigestInputStream ;
31
36
import java .security .MessageDigest ;
37
+ import java .security .NoSuchAlgorithmException ;
32
38
import java .security .SecureRandom ;
33
39
import java .util .Base64 ;
34
40
import java .util .List ;
35
41
import java .util .Map ;
36
42
import java .util .Optional ;
43
+ import java .util .Random ;
37
44
import java .util .UUID ;
45
+ import java .util .concurrent .CompletableFuture ;
38
46
import java .util .zip .CRC32 ;
39
47
import java .util .concurrent .ExecutorService ;
40
48
import java .util .concurrent .Executors ;
48
56
import org .junit .jupiter .api .Timeout ;
49
57
import org .reactivestreams .Subscriber ;
50
58
import software .amazon .awssdk .core .ClientType ;
59
+ import software .amazon .awssdk .core .ResponseBytes ;
51
60
import software .amazon .awssdk .core .ResponseInputStream ;
52
61
import software .amazon .awssdk .core .async .AsyncRequestBody ;
62
+ import software .amazon .awssdk .core .async .AsyncResponseTransformer ;
63
+ import software .amazon .awssdk .core .async .BlockingInputStreamAsyncRequestBody ;
53
64
import software .amazon .awssdk .core .interceptor .Context ;
54
65
import software .amazon .awssdk .core .interceptor .ExecutionAttributes ;
55
66
import software .amazon .awssdk .core .interceptor .ExecutionInterceptor ;
56
67
import software .amazon .awssdk .core .internal .async .FileAsyncRequestBody ;
57
68
import software .amazon .awssdk .core .sync .ResponseTransformer ;
58
69
import software .amazon .awssdk .services .s3 .S3AsyncClient ;
70
+ import software .amazon .awssdk .services .s3 .S3Client ;
59
71
import software .amazon .awssdk .services .s3 .S3IntegrationTestBase ;
60
72
import software .amazon .awssdk .services .s3 .model .ChecksumAlgorithm ;
61
73
import software .amazon .awssdk .services .s3 .model .ChecksumMode ;
62
74
import software .amazon .awssdk .services .s3 .model .CompleteMultipartUploadRequest ;
63
75
import software .amazon .awssdk .services .s3 .model .CreateMultipartUploadRequest ;
76
+ import software .amazon .awssdk .services .s3 .model .GetObjectRequest ;
64
77
import software .amazon .awssdk .services .s3 .model .GetObjectResponse ;
78
+ import software .amazon .awssdk .services .s3 .model .PutObjectResponse ;
65
79
import software .amazon .awssdk .services .s3 .model .UploadPartRequest ;
66
80
import software .amazon .awssdk .services .s3 .utils .ChecksumUtils ;
81
+ import software .amazon .awssdk .testutils .FileUtils ;
82
+ import software .amazon .awssdk .testutils .RandomTempFile ;
83
+ import software .amazon .awssdk .utils .BinaryUtils ;
67
84
import software .amazon .awssdk .utils .IoUtils ;
68
85
import software .amazon .awssdk .utils .Md5Utils ;
69
86
@@ -72,9 +89,8 @@ public class S3MultipartClientPutObjectIntegrationTest extends S3IntegrationTest
72
89
73
90
private static final String TEST_BUCKET = temporaryBucketName (S3MultipartClientPutObjectIntegrationTest .class );
74
91
private static final String TEST_KEY = "testfile.dat" ;
75
- private static final int OBJ_SIZE = 19 * 1024 * 1024 ;
92
+ private static final int OBJ_SIZE = 1024 * 1024 * 30 ;
76
93
private static final CapturingInterceptor CAPTURING_INTERCEPTOR = new CapturingInterceptor ();
77
- private static final byte [] CONTENT = RandomStringUtils .randomAscii (OBJ_SIZE ).getBytes (Charset .defaultCharset ());
78
94
private static File testFile ;
79
95
private static S3AsyncClient mpuS3Client ;
80
96
private static ExecutorService executorService = Executors .newFixedThreadPool (2 );
@@ -83,8 +99,8 @@ public class S3MultipartClientPutObjectIntegrationTest extends S3IntegrationTest
83
99
public static void setup () throws Exception {
84
100
setUp ();
85
101
createBucket (TEST_BUCKET );
86
- testFile = File . createTempFile ( "SplittingPublisherTest" , UUID . randomUUID (). toString ());
87
- Files . write ( testFile . toPath (), CONTENT );
102
+
103
+ testFile = new RandomTempFile ( OBJ_SIZE );
88
104
mpuS3Client = S3AsyncClient
89
105
.builder ()
90
106
.region (DEFAULT_REGION )
@@ -108,6 +124,26 @@ public void reset() {
108
124
CAPTURING_INTERCEPTOR .reset ();
109
125
}
110
126
127
+ @ Test
128
+ public void upload_blockingInputStream_shouldSucceed () throws IOException {
129
+ String objectPath = UUID .randomUUID ().toString ();
130
+ String expectedMd5 = Md5Utils .md5AsBase64 (testFile );
131
+
132
+ BlockingInputStreamAsyncRequestBody body = AsyncRequestBody .forBlockingInputStream (null );
133
+
134
+ CompletableFuture <PutObjectResponse > put =
135
+ mpuS3Client .putObject (req -> req .bucket (TEST_BUCKET ).key (objectPath )
136
+ .build (), body );
137
+ body .writeInputStream (new FileInputStream (testFile ));
138
+ put .join ();
139
+
140
+ ResponseInputStream <GetObjectResponse > objContent = s3 .getObject (r -> r .bucket (TEST_BUCKET ).key (objectPath ),
141
+ ResponseTransformer .toInputStream ());
142
+
143
+ String actualMd5 = BinaryUtils .toBase64 (Md5Utils .computeMD5Hash (objContent ));
144
+ assertEquals (expectedMd5 , actualMd5 );
145
+ }
146
+
111
147
@ Test
112
148
void putObject_fileRequestBody_objectSentCorrectly () throws Exception {
113
149
AsyncRequestBody body = AsyncRequestBody .fromFile (testFile .toPath ());
@@ -127,7 +163,7 @@ void putObject_fileRequestBody_objectSentCorrectly() throws Exception {
127
163
@ Test
128
164
void putObject_inputStreamAsyncRequestBody_objectSentCorrectly () throws Exception {
129
165
AsyncRequestBody body = AsyncRequestBody .fromInputStream (
130
- new ByteArrayInputStream ( CONTENT ),
166
+ new FileInputStream ( testFile ),
131
167
Long .valueOf (OBJ_SIZE ),
132
168
executorService );
133
169
mpuS3Client .putObject (r -> r .bucket (TEST_BUCKET )
@@ -193,7 +229,7 @@ public void subscribe(Subscriber<? super ByteBuffer> s) {
193
229
@ Test
194
230
void putObject_withSSECAndChecksum_objectSentCorrectly () throws Exception {
195
231
byte [] secretKey = generateSecretKey ();
196
- String b64Key = Base64 . getEncoder ().encodeToString (secretKey );
232
+ String b64Key = getEncoder ().encodeToString (secretKey );
197
233
String b64KeyMd5 = Md5Utils .md5AsBase64 (secretKey );
198
234
199
235
AsyncRequestBody body = AsyncRequestBody .fromFile (testFile .toPath ());
@@ -282,17 +318,10 @@ private static String calculateCRC32AsString(String filePath) throws IOException
282
318
IoUtils .drainInputStream (cis );
283
319
long checksumValue = cis .getChecksum ().getValue ();
284
320
byte [] checksumBytes = ByteBuffer .allocate (4 ).putInt ((int ) checksumValue ).array ();
285
- return Base64 . getEncoder ().encodeToString (checksumBytes );
321
+ return getEncoder ().encodeToString (checksumBytes );
286
322
}
287
323
}
288
324
289
- private static String calculateSHA1AsString () throws Exception {
290
- MessageDigest md = MessageDigest .getInstance ("SHA-1" );
291
- md .update (CONTENT );
292
- byte [] checksum = md .digest ();
293
- return Base64 .getEncoder ().encodeToString (checksum );
294
- }
295
-
296
325
private static byte [] generateSecretKey () {
297
326
KeyGenerator generator ;
298
327
try {
0 commit comments