File Upload on Amazon S3 server via REST API call

10 / Apr / 2015 by Lovin Saini 5 comments

We Can upload file on Amazon S3 Server directly without intervention of web server by using REST API call on S3 Server.

Use Case : File upload was required on mobile app without integrating SDK because integrating SDK causes app to be heavier in size and also if it goes through our web server than it would be unnecessary consumption of resources . So for that we directly made a REST api call to Amazon S3 server.

Following are the Required Inputs :

  • Date in a specific format RFC 2822.
  • Bucket name which is already created on S3.
  • File which needs to be uploaded.
  • ContentType is the type of file.
  • Access Key of S3 server.
  • Secret key of S3 Server.
  • Base64 Encoded Signature by using S3 secret key .First we will create signature string using content-type, date and resource.This string will be base 64 encoded using S3 secret key which will be our signature.

Code written in groovy for REST API call :
[groovy]
import sun.misc.BASE64Encoder
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

Long BUFFER_SIZE = 4096;
String method = "PUT";
String bucket = "BUCKET_OF_S3_SERVER"
String secretKey = "SECRET_KEY_OF_S3_SERVER"
String filePath = "FILE_NAME"
SimpleDateFormat df = new SimpleDateFormat("EEE’, ‘dd’ ‘MMM’ ‘yyyy’ ‘HH:mm:ss’ ‘Z", Locale.US);
Date date = new Date()
String formattedDate = df.format(date)
File uploadFile = new File(filePath);
if (!(uploadFile.isFile() && uploadFile.exists())) {
println ‘File Not Found !!!!’
return;
}

URL url = new URL("http://${bucket}.s3.amazonaws.com/" + uploadFile.name);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
String resource = "/" + bucket + "/" + uploadFile.name
String contentType = "application/octet-stream"
String signn = method + "\n\n" + contentType + "\n" + formattedDate + "\n" + resource
Mac hmac = Mac.getInstance("HmacSHA1");
hmac.init(new SecretKeySpec(
secretKey.getBytes("UTF-8"), "HmacSHA1"));
String signature = (new BASE64Encoder()).encode(
hmac.doFinal(signn.getBytes("UTF-8")))
.replaceAll("\n", "");

String authAWS = "AWS " + "ACCESS_KEY_OF_S3_SERVER" + ":" + signature
httpConn.setDoOutput(true);
httpConn.setRequestMethod(method);
httpConn.setRequestProperty("Accept", "*/*");
httpConn.setRequestProperty("Date", formattedDate);
httpConn.setRequestProperty("Content-type", contentType);
httpConn.setRequestProperty("Authorization",authAWS);
OutputStream outputStream = httpConn.getOutputStream();
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
println "Response message : "+httpConn.getResponseMessage();
[/groovy]
 

FOUND THIS USEFUL? SHARE IT

comments (5)

  1. Tausif

    Strange but keeping a space at the end of the key in setRequestProperty method did the trick.
    httpConn.setRequestProperty(“Accept “, “*/*”);
    httpConn.setRequestProperty(“Date “, formattedDate);
    httpConn.setRequestProperty(“Content-type “, contentType);
    httpConn.setRequestProperty(“Authorization “,authAWS);

    Reply
  2. Lovin

    First try to execute curl with your request parameters, as per the following blog, It would make it easy to debug. Once you get it working then move on rest api based call.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *