htmlフォームからs3にアップロードしようとしたら、policyとsignatureをbase64でエンコードしないと駄目なので、変換プログラミングがないと厳しい!素直にAWS SDK for javascriptを使おう!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!-- アップロード先s3のURL --> <form action="http://XXXXX.s3.amazonaws.com/" method="post" enctype="multipart/form-data"> <!-- アップロードしたパス付きファイル名を記述。ローカルのファイル名とは違っても良い --> <input type="hidden" name="key" value="uploads/myfilename.jpg"> <!-- AWSアスセスキーを記述 --> <input type="hidden" name="AWSAccessKeyId" value="あなたの AWS アクセスキー"> <!-- アップロード後のファイルのアクセス権。public-readで誰でも見れるようにする --> <input type="hidden" name="acl" value="public-read"> <!-- アップロード後のリダイレクト先--> <input type="hidden" name="success_action_redirect" value="https://www.google.co.jp"> <input type="hidden" name="policy" value="ポリシーファイルのBase64エンコード"> <input type="hidden" name="signature" value="シグネチャ"> <!-- アップロードファイルのMIME --> <input type="hidden" name="Content-Type" value="image/jpeg"> <!-- ファイルを選択 --> <input name="file" type="file"> <!-- 送信ボタン --> <input type="submit" value="S3 へのアップロード"> </form> |
そう考えると、htmlフォーム@s3 → lambda -> s3へアップロードが簡単かな?
公式に「ブラウザから Amazon S3 への写真のアップロード」があったので実装してみよう。
S3+JSで行けるかと思ったら、cognitoも必要なのか…。
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/s3-example-photo-album.html
グダグダ言っててもしょうがないので、とりあえずやってみるか
cognitoじゃなくて、普通のIAMユーザにs3フルアクセス権限を与えて、アクセスキー&シークレットキーで認証しよう(ソースで丸見えになるから本当は駄目です!!)
1, s3バケットを作成。パブリックにアクセス可能にしておく
1-a, ブロックパブリックアクセス (バケット設定)を4つともオフ!
2-b, パケットポリシーを設定。Bucket-Nameだけ書き換えする。s3のファイル取得のみ可
この状態にすると、s3にアップロードしたファイルはURLにアスセスすれば表示される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::Bucket-Name/*" ] } ] } |
2, CORS(Cross-Origin Resource Sharing)設定
別のドメイン(localhost)からでもアクセスできるように設定する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "HEAD", "GET", "PUT", "POST", "DELETE" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [ "ETag" ] } ] |
3, s3にアクセスするためのユーザを作る(アクセスキーだけって作れないのか~!?)
3-1, iamユーザを作る
3-2, AmazonS3FullAccessポリシーを、作ったユーザにアタッチする
3-3, アクセスキーとアクセスシークレットが表示されるのでメモしておく。
※忘れたら2つまで作れるので、新規に作っても良い。
4, ようやくコーディング。土台となるhtmlとアップロード処理のJSを作る。
AWSのSDKの最新バージョンは、以下のサイトから確認する
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html
アルバム機能と削除機能は不要なので削除した。アップロード機能と写真一覧機能のみ!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
<!DOCTYPE html> <html> <head> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.983.0.min.js"></script> <script> var BucketName = ""; //作ったs3バケット名 var bucketRegion = "ap-northeast-1"; // 東京 // s3へのアクセス権限があるユーザ var accessKey = ""; // アクセスキー var secretKey = ""; //シークレットキー // 認証 AWS.config.update({ region: bucketRegion, credentials: new AWS.Credentials(accessKey, secretKey) }); // S3オブジェクトを生成 var s3 = new AWS.S3({ apiVersion: "2006-03-01", params: { Bucket: BucketName } }); </script> <script> // 写真一覧を表示する function listPhotos() { // ルート直下のファイル一覧を取得 s3.listObjects({ Prefix: "" }, function(err, data) { if (err) { return alert("写真一覧に失敗! " + err.message); } // s3バケットURLを生成 var href = this.request.httpRequest.endpoint.href; var bucketUrl = href + BucketName + "/"; // 写真URLリストを生成 var photos = data.Contents.map(function(photo) { var photoKey = photo.Key; // ファイル名 var photoUrl = bucketUrl + encodeURIComponent(photoKey); // ブラウザに表示するHTMLを生成 return getHtml([ photoKey, '<a href="' + photoUrl + '" target=new>', '<img style="height:128px;" src="' + photoUrl + '"/>', '</a><br>' ]); }); // アップロードファイルの選択ボタンと送信ボタン var htmlTemplate = [ '<input id="photoupload" type="file" accept="image/*">', '<button id="addphoto" onclick="addPhoto()">', "写真をアップロード", "</button>", "<div>", getHtml(photos), "</div>" ]; document.getElementById("app").innerHTML = getHtml(htmlTemplate); }); } // 写真アップロード function addPhoto() { //ファイルを取得! var files = document.getElementById("photoupload").files; if (!files.length) { return alert("ファイルを選択して下さい"); } // アップロードの設定値 var upload = new AWS.S3.ManagedUpload({ params: { Bucket: BucketName, Key: files[0].name, // s3バケットのルート直下にアップロード Body: files[0], // ファイル本体 // MIMEタイプを指定しないとoctet-streamになってダウンロードされてしまう // ContentType: files[0].mimetype, // なんか取得できない。 ContentType: 'image/jpeg', ACL: 'public-read' // 公開&リードオンリー } }); // 実際のアップロード処理 var promise = upload.promise(); promise.then( function(data) { alert("アップロード成功"); listPhotos(); }, function(err) { return alert("アップロード失敗! ", err.message); } ); } </script> <script> function getHtml(template) { return template.join('\n'); } listPhotos(); </script> </head> <body> <div id="app"></div> </body> </html> |