ブラウザからS3に直接ファイルをアップロードする
CloudデザインパターンのDirect Object UploadパターンをJavaで作る際のメモ
CDP:Direct Object Uploadパターン - AWS-CloudDesignPattern
Browser Uploads to S3 using HTML POST Forms : Articles & Tutorials : Amazon Web Services
こちらを参考にHTMLを作成する
<html> <head> <title>S3 POST Form</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <form action="https://【バケット名】.s3.amazonaws.com/" method="post" enctype="multipart/form-data"> <input type="hidden" name="key" value="【パス(任意)】${filename}"> <input type="hidden" name="AWSAccessKeyId" value="【AWSアクセスキー】"> <input type="hidden" name="acl" value="private"> <input type="hidden" name="success_action_redirect" value="【リダイレクト先URL】"> <input type="hidden" name="policy" value="【ポリシー】"> <input type="hidden" name="signature" value="【シグネチャ】"> <input type="hidden" name="Content-Type" value="${Content-Type}"> <!-- Include any additional input fields here --> File to upload to S3: <input name="file" type="file"> <br> <input type="submit" value="Upload File to S3"> </form> </body> </html>
public static void main(String[] args) throws Exception { String secretAccessKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // 有効期限 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, 1); String policy_document = "{\"expiration\": \"" + sdf.format(cal.getTime()) + "\"," + "\"conditions\": [" + "{\"bucket\": \"【バケット名】\"}," + "[\"starts-with\", \"$key\", \"【パス(任意)】\"]," + "{\"acl\": \"private\"}," + "{\"success_action_redirect\": \"【リダイレクト先URL】\"}," + "[\"starts-with\", \"$Content-Type\", \"\"]," + "[\"content-length-range\", 0, 1048576]" + "]" + "}"; String policy = (new BASE64Encoder()).encode(policy_document.getBytes("UTF-8")).replaceAll("\n", "").replaceAll("\r", ""); // ポリシー System.out.println(policy); Mac hmac = Mac.getInstance("HmacSHA1"); hmac.init(new SecretKeySpec(secretAccessKey.getBytes("UTF-8"), "HmacSHA1")); String signature = (new BASE64Encoder()).encode(hmac.doFinal(policy.getBytes("UTF-8"))).replaceAll("\n", ""); // シグネチャ System.out.println(signature); }
ポリシーにはformと同じ値を設定しないとアップロード時にエラーになるので注意
(おまけ)JavaのHTTPクライアントから利用してみる
public static void main(String[] args) throws ClientProtocolException, IOException, InvalidKeyException, NoSuchAlgorithmException { DefaultHttpClient httpclient = new DefaultHttpClient(); String url = "https://【バケット名】.s3.amazonaws.com/"; // アップロードするファイル File file = new File("src/main/resources/hoge.jpg"); MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Charset.forName("UTF-8")); String mime = "text/plain"; Charset utf8 = Charset.forName("UTF-8"); reqEntity.addPart("key", new StringBody("【パス(任意)】${filename}", mime, utf8)); reqEntity.addPart("AWSAccessKeyId", new StringBody("【AWSアクセスキー】", mime, utf8)); reqEntity.addPart("acl", new StringBody("private", mime, utf8)); reqEntity.addPart("success_action_redirect", new StringBody("【リダイレクト先URL】", mime, utf8)); reqEntity.addPart("policy", new StringBody("【ポリシー】", mime, utf8)); reqEntity.addPart("signature", new StringBody("【シグネチャ】", mime, utf8)); reqEntity.addPart("Content-Type", new StringBody("${Content-Type}", mime, utf8)); reqEntity.addPart("file", new FileBody(file)); // POSTリクエストを送信 HttpPost request = new HttpPost(url); request.setEntity(reqEntity); HttpResponse response = httpclient.execute(request); HttpEntity resEntity = response.getEntity(); // 結果を出力 IOUtils.copy(resEntity.getContent(), System.out); }
2012/09/11追記
有効期限はSimpleDateFormatを使用して文字列化していたがAWSのSDKには
「com.amazonaws.util.DateUtils」クラスが用意されているのでこちらを使うべきだと思われる
Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, 1); String limit = new DateUtils().formatIso8601Date(cal.getTime());