1 package com.example.s3; 2 3 import java.io.*; 4 import java.util.concurrent.*; 5 import com.amazonaws.s3.model.*; 6 import com.amazonaws.s3.*; 7 import software.amazon.awssdk.crt.Log; 8 import software.amazon.awssdk.crt.auth.credentials.*; 9 import software.amazon.awssdk.crt.io.*; 10 11 public class PutGet { main(String[] args)12 public static void main(String[] args) { 13 final String USAGE = "\n" 14 + "Upload file to S3, then download it.\n\n" 15 + "Usage:\n" 16 + " PutGet <bucket> <key> <filepath> <region> [throughput] [part-size]\n\n" 17 + "Where:\n" 18 + " bucket: S3 bucket name.\n\n" + " key: S3 key name.\n\n" 19 + " filepath: File to upload. Then downloaded with '.download' suffix.\n\n" 20 + " region: Signing region. ex: us-east-1\n\n" 21 + " throughput: Target throughput in gigabits per second (default 25.0)\n\n" 22 + " part-size: Size in bytes of each multipart upload (default 8MB)\n\n"; 23 if (args.length < 4) { 24 System.out.print(USAGE); 25 System.exit(1); 26 } 27 28 String bucket = args[0]; 29 String key = args[1]; 30 String putFilepath = args[2]; 31 String getFilepath = putFilepath + ".download"; 32 String signingRegion = args[3]; 33 34 long partSizeBytes = 8 * 1024 * 1024; // 8MB 35 if (args.length > 4) 36 partSizeBytes = Long.parseLong(args[4]); 37 38 double targetThroughputGbps = 25.0; 39 if (args.length > 5) 40 targetThroughputGbps = Double.parseDouble(args[5]); 41 42 Log.initLoggingToStderr(Log.LogLevel.Error); 43 44 // try-with-resources to ensure these resources get closed 45 try (EventLoopGroup eventLoopGroup = new EventLoopGroup(0 /* cpuGroup */, 0 /* numThreads 0=default */); 46 HostResolver hostResolver = new HostResolver(eventLoopGroup, 256 /* maxEntries */); 47 ClientBootstrap clientBootstrap = new ClientBootstrap(eventLoopGroup, hostResolver); 48 49 // default provider searches for AWS credentials in places like 50 // ~/.aws/credentials and env vars AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY 51 CredentialsProvider credentialsProvider = new DefaultChainCredentialsProvider.DefaultChainCredentialsProviderBuilder() 52 .withClientBootstrap(clientBootstrap).build(); 53 54 S3NativeClient s3Client = new S3NativeClient(signingRegion, clientBootstrap, credentialsProvider, 55 partSizeBytes, targetThroughputGbps);) { 56 57 System.out.println("Uploading..."); 58 File putFile = new File(putFilepath); 59 PutObjectRequest putRequest = PutObjectRequest.builder().bucket(bucket).key(key) 60 .contentLength(putFile.length()).build(); 61 PutDataSupplier putDataSupplier = new PutGet.PutDataSupplier(putFile); 62 CompletableFuture<PutObjectOutput> putFuture = s3Client.putObject(putRequest, putDataSupplier); 63 try { 64 putFuture.get(); 65 } catch (InterruptedException | ExecutionException e) { 66 throw new RuntimeException(e); 67 } 68 System.out.println("Upload complete"); 69 70 System.out.println("Downloading..."); 71 GetObjectRequest getRequest = GetObjectRequest.builder().bucket(bucket).key(key).build(); 72 GetDataConsumer getDataConsumer = new PutGet.GetDataConsumer(getFilepath); 73 CompletableFuture<GetObjectOutput> getFuture = s3Client.getObject(getRequest, getDataConsumer); 74 try { 75 getFuture.get(); 76 } catch (InterruptedException | ExecutionException e) { 77 throw new RuntimeException(e); 78 } 79 System.out.println("Download complete"); 80 } 81 } 82 83 // Supplies the file body to upload for PUT 84 static class PutDataSupplier implements RequestDataSupplier { 85 FileInputStream stream; 86 PutDataSupplier(File file)87 public PutDataSupplier(File file) { 88 try { 89 stream = new FileInputStream(file); 90 } catch (FileNotFoundException e) { 91 throw new RuntimeException(e); 92 } 93 } 94 getRequestBytes(byte[] buffer)95 public boolean getRequestBytes(byte[] buffer) { 96 int progress = 0; 97 while (progress < buffer.length) { 98 try { 99 int result = stream.read(buffer, progress, buffer.length - progress); 100 if (result == -1) 101 return true; 102 progress += result; 103 } catch (IOException e) { 104 throw new RuntimeException(e); 105 } 106 } 107 return false; 108 } 109 onFinished()110 public void onFinished() { 111 try { 112 stream.close(); 113 } catch (IOException e) { 114 throw new RuntimeException(e); 115 } 116 } 117 } 118 119 // Receives the downloaded file body from GET 120 static class GetDataConsumer implements ResponseDataConsumer { 121 FileOutputStream stream; 122 GetDataConsumer(String filepath)123 public GetDataConsumer(String filepath) { 124 try { 125 stream = new FileOutputStream(filepath); 126 } catch (FileNotFoundException e) { 127 throw new RuntimeException(e); 128 } 129 } 130 onResponseData(byte[] bodyBytesIn)131 public void onResponseData(byte[] bodyBytesIn) { 132 try { 133 stream.write(bodyBytesIn); 134 } catch (IOException e) { 135 throw new RuntimeException(e); 136 } 137 } 138 onFinished()139 public void onFinished() { 140 try { 141 stream.close(); 142 } catch (IOException e) { 143 throw new RuntimeException(e); 144 } 145 } 146 } 147 } 148