1. komakomako

    No comment

    komakomako
Changes in tags
Changes in body
Source | HTML | Preview
@@ -1,205 +1,219 @@
[こちら](http://qiita.com/yuku_t/items/40b7daf018d3dab48974)を参考に, 画像をブラウザからS3へ直接アップロードできるようにしました.
# 1. AWSの準備 (時間:5分)
IAMでS3アクセス用のユーザを作成します. まずは以下のようにコンソール画面からIAMへアクセス.
<img width="500" alt="ss 2017-09-18 12.44.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/7ffd7963-918d-d7ee-e328-7fd87975ca27.png">
-次に, 以下のUserをクリック
+次に, 以下のUsersをクリック
<img width="500" alt="ss 2017-09-18 12.48.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/7d7bbddb-7fea-651a-ab6a-a60c39b0e40e.png">
Add userをクリック
<img width="500" alt="ss 2017-09-18 12.48.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/c7520ae6-0315-5333-b687-77fa65d2e3fb.png">
任意の名前を入力. プログラマティックアクセスにチェックして次へ.
<img width="500" alt="ss 2017-09-18 12.48.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/9ba6d82b-4065-9a85-5b63-18944c2d5548.png">
既存ポリシーの中から AmazonS3FullAccessを見つけてチェック.
<img width="500" alt="eee" src="https://qiita-image-store.s3.amazonaws.com/0/80357/86d326f3-9174-621b-3c34-7535e3dd7a5b.png">
以上でユーザ作成は完了. 詳細画面でCreate Access keyをクリックして必要なキーを取得する.
<img width="500" alt="aaa" src="https://qiita-image-store.s3.amazonaws.com/0/80357/aca0cdc0-0c55-794c-0812-afe4b63bb43c.png">
このようにkeyIDとシークレットkeyが表示されるので, メモっておく.
<img width="500" alt="ss 2017-09-18 12.50.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/030f4b36-ef35-7119-06f9-a83d673c3622.png">
次にS3の設定を行う.
適当なバケットを作成する. 各種設定はデフォルトのままで良い. 作成し終えたら, そのバケットのプロパティを開き, Permissions -> CORS configurationに以下のように記述する. これで終わり.
<img width="500" alt="ssd" src="https://qiita-image-store.s3.amazonaws.com/0/80357/6c4bd597-4055-1418-0828-d94b00dc9b49.png">
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+<CORSRule>
+ <AllowedOrigin>*</AllowedOrigin>
+ <AllowedMethod>GET</AllowedMethod>
+ <AllowedMethod>POST</AllowedMethod>
+ <AllowedMethod>PUT</AllowedMethod>
+ <MaxAgeSeconds>3000</MaxAgeSeconds>
+ <AllowedHeader>*</AllowedHeader>
+</CORSRule>
+</CORSConfiguration>
+```
+
# 2. バックエンドでS3ポリシーを作成
自身のRailsアプリに, POSTメソッドで叩ける適当なエンドポイントを作成する.
`routes.rb`に例えば以下のように記述.
```ruby
post 'image_upload', to: 'images#upload'
```
そして, `images#upload`を次のように定義する.
```ruby
class ImagesController < ApplicationController
# Deviceを使って認証処理をしている場合, 次の1行によって認証を要求できる.
before_action :authenticate_user!, only: [:upload]
# 先ほど作ったバケットの名前とアクセスKeyIdとシークレットkey
S3_BUCKET = 'your-bucket-name'
AWS_ACCESS_KEY_ID = 'XXX'
AWS_SECRET_KEY = 'XXX'
def upload
# アップロード後のファイル名
key = 'hogehoge'
acl = 'public-read'
ctype = params[:content_type]
# ポリシー作成
policy_document = {
# 1分間のみ有効
expiration: (Time.now + 1.minute).utc,
conditions: [
# アップロード先のS3バケット
{ bucket: S3_BUCKET },
# ファイルの権限
{ acl: acl },
# ファイル名
{ key: key },
# ファイルの形式
{ 'Content-Type' => ctype },
# アップロード可能なファイルのサイズ
['content-length-range', params[:size], params[:size]]
]
}.to_json
policy = Base64.encode64(policy_document).gsub("\n", '')
# signatureの作成
signature = Base64.encode64(
OpenSSL::HMAC.digest(
OpenSSL::Digest::Digest.new('sha1'),
AWS_SECRET_KEY, policy)).gsub('\n', '')
# アップロードに必要な情報をJSON形式でクライアントに返す
render json: {
url: "https://#{S3_BUCKET}.s3.amazonaws.com/",
form: {
AWSAccessKeyId: AWS_ACCESS_KEY_ID,
signature: signature,
policy: policy,
key: key,
acl: acl,
'Content-Type' => ctype
}
}
end
end
```
# 3. フロントエンドでポリシー取得しアップロード実行
画像をアップロードしたいViewに, 以下のようなjavascriptを仕込みます.
```html
画像を投稿します
<div style="width: 500px">
<form enctype="multipart/form-data" method="post">
<input type="file" name="userfile" accept="image/*">
</form>
</div>
<div id="thumbnail" style="max-width: 100px;">
<img src="/plus.png" id="image_to_upload">
</div>
<button class="btn btn-primary" id="upload">投稿</button>
<script type="text/javascript">
$(function() {
var file = null;
// アップロードするファイルを選択
$('input[type=file]').change(function() {
file = $(this).prop('files')[0];
// 画像以外は処理を停止させるためファイル形式をチェック
if (file.type != 'image/jpeg' && file.type != 'image/png') {
// 画像でない場合は消す
var img_src = $('<img>').attr('src', '/plus.png')
$('#thumbnail').html(img_src);
file = null
return;
}
// サムネ表示
var reader = new FileReader();
reader.onload = function() {
var img_src = $('<img>').attr('src', reader.result)
img_src.css('width', '500px');
$('#thumbnail').html(img_src);
}
reader.readAsDataURL(file);
});
// アップロードボタンクリック
$('#upload').click(function(){
// ファイルが指定されていなければ何も起こらない
if(!file) {
return;
}
// ポリシーを発行する
$.ajax({
url: 'http://localhost:3000/image_upload',
type: 'POST',
data: {
content_type: file.type,
size: file.size
}
})
.done(function( data, textStatus, jqXHR ) {
// 取得したポリシーをフォームデータの形に整形する
var name, fd = new FormData();
for (name in data.form) if (data.form.hasOwnProperty(name)) {
fd.append(name, data.form[name]);
}
fd.append('file', file); // ファイルを添付
$.ajax({
url: data.url,
type: 'POST',
dataType: 'json',
data: fd,
processData: false,
contentType: false
})
.done(function( data, textStatus, jqXHR ) {
console.log('success!')
})
.fail(function( jqXHR, textStatus, errorThrown ) {
// アップロード時のエラー
console.log('error: 2');
});
})
.fail(function( jqXHR, textStatus, errorThrown ) {
// ポリシー取得時のエラー
console.log('error: 1');
});
});
});
</script>
```
次のようなUIが出来上がります. 「ファイルを選択」をクリックしてファイルを適当に選択すると, サムネイルが表示されます. この状態で投稿ボタンを押すと画像がS3へ直接アップロードされます.
<img width="500" alt="ss 2017-09-18 13.16.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/d6e23d56-8573-41df-1737-ea62e778f606.png">
以上です.