Skip to content

Instantly share code, notes, and snippets.

@yuku
Last active December 17, 2015 18:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuku/5655239 to your computer and use it in GitHub Desktop.
Save yuku/5655239 to your computer and use it in GitHub Desktop.
Qiitaの画像アップロード機能も簡単に実装できる。そう、S3ならね。 ref: http://qiita.com/yuku_t/items/40b7daf018d3dab48974
S3_BUCKET = 'xxx'
AWS_SECRET_KEY = 'xxx'
AWS_ACCESS_KEY_ID = 'xxx'
# アクセスしてきたクライアントにS3へアップロードするためのpolicyと
# それをハッシュ化したsignatureを返す。
def policies
# 0. セッションの確認など
# 1. 画像情報をバリデーションする
# ファイルサイズは大き過ぎないか、種類は適切か、など。
# 2. policyを作る
# policyで許可した内容しかクライアントはアップロードできなくなる。
key = '/path/to/file' # アップロード先のパス
policy_document = {
expiration: (Time.now + 1.minute).utc, # このポリシーは1分間のみ有効
conditions: [
# アップロード先のS3バケットを指定する
{ bucket: S3_BUCKET },
# ファイルのS3上でのパスを指定する。
# ワイルドカードも指定できるが、完全一致させておく。
{ key: key },
# オプション。クライアントから送られてきたものそのままにする。
{ 'Content-Type' => params[:content_type] },
# オプション。アップロード可能なファイルのサイズを範囲で指定できる。
# クライアントから送られてきたファイルサイズをそのまま指定することで
# 1バイトでも大きさの異なるファイルは拒否できる。
['content-length-range', params[:size], params[:size]]
]
}.to_json
policy = Base64.encode64(policy_document).gsub("\n", '')
# 3. signatureを作る
# AWSのシークレットキーとpolicyからsignatureを作る。
# signatureはシークレットキーを知っている人しか計算できないので
# クライアントがpolicyを改ざんしてもAmazon側がそれを検知できる。
signature = Base64.encode64(
OpenSSL::HMAC.digest(
OpenSSL::Digest::Digest.new('sha1'),
AWS_SECRET_KEY, policy)).gsub("\n", '')
# 4. アップロードに必要な情報をクライアントに返す
return {
url: "https://#{S3_BUCKET}.s3.amazonaws.com/",
form: {
'AWSAccessKeyId' => AWS_ACCESS_KEY_ID,
signature: signature,
policy: policy,
key: key
}
}
end
var fileInput = $('input[type="file"]');
fileInput.on('change', function (e) {
var file = e.target.files[0];
// 0. 事前にファイルの大きさや種類をチェックする
// 1. サーバからpolicyとsignatureをもらう
// 上図でいう(1)に対応
$.ajax({
url: '/policies',
type: 'POST'
dataType: 'json'
data: {
// サーバにこれからアップロードするファイルの情報を渡す。
size: file.size, // ファイルの大きさ
content_type: file.type // ファイルの形式
}
}).done(function (data) {
// 2. サーバが返した情報をそのまま使ってFormDataを作る
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); // ファイルも忘れずに添付する
// 送信
// 上図でいう(3)に対応
var xhr = new XMLHttpRequest();
xhr.open('POST', data.url, true)
xhr.send(fd);
})
});
var fileInput = $('input[type="file"]');
fileInput.on('change', function (e) {
var file = e.target.files[0];
// 0. 事前にファイルの大きさや種類をチェックする
// 1. サーバからpolicyとsignatureをもらう
// 上図でいう(1)に対応
$.ajax({
url: '/policies',
type: 'POST'
dataType: 'json'
data: {
// サーバにこれからアップロードするファイルの情報を渡す。
size: file.size, // ファイルの大きさ
content_type: file.type // ファイルの形式
}
}).done(function (data) {
// 2. サーバが返した情報をそのまま使ってFormDataを作る
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); // ファイルも忘れずに添付する
// 送信
// 上図でいう(3)に対応
var xhr = new XMLHttpRequest();
xhr.open('POST', data.url, true)
xhr.send(fd);
})
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment