Javascript AWS SDKを使用してファイルをS3にアップロードしますが、認証情報はまったく使用しません。認証情報を使用してアップロードすることはできますが、アプリユーザーごとにAWS IAMユーザーを生成することはできません(または必要ですか?)
したがって、GETを使用するのと同様に、サーバーに事前署名されたURLを生成し、ブラウザーに送信して、ブラウザーにそのURLにアップロードしてもらいます。
ただし、これを実現する方法の例はありません。また、資格情報を設定しない場合、S3へのアップロードリクエストを行う前であっても、SDKは
code: "CredentialsError"
message: "No credentials to load"
JS SDKのドキュメントではこれについて言及されているため、可能性があると思われます。
Pre-signing a putObject (asynchronously)
var params = {Bucket: 'bucket', Key: 'key'};
s3.getSignedUrl('putObject', params, function (err, url) {
console.log('The URL is', url);
});
古い質問を静かにしてください、しかしそれは最終的にそれを成し遂げるために私を少し助けました。私のソリューションは、PHPとjQueryを使用したJavaScriptに基づいています。
https://github.com/JoernBerkefeld/s3SignedUpload でソリューション全体をきれいにラップしていますが、ここに不可欠なものがあります。
api.php:
<?php
require_once '/server/path/to/aws-autoloader.php';
use Aws\Common\Aws;
$BUCKET = "my-bucket";
$CONFIG = "path-to-iam-credentials-file-relative-to-root.php"
function getSignedUrl($filename, $mime) {
$S3 = Aws::factory( $CONFIG )->get('S3');
if(!$filename) {
return $this->error('filename missing');
}
if(!$mime) {
return $this->error('mime-type missing');
}
$final_filename = $this->get_file_name($filename);
try {
$signedUrl = $S3->getCommand('PutObject', array(
'Bucket' => $BUCKET,
'Key' => $this->folder . $final_filename,
'ContentType' => $mime,
'Body' => '',
'ContentMD5' => false
))->createPresignedUrl('+30 minutes');
} catch (S3Exception $e) {
echo $e->getMessage() . "\n";
}
$signedUrl .= '&Content-Type='.urlencode($mime);
return $signedUrl;
}
echo getSignedUrl($_GET['filename'],$_GET['mimetype']);
必ず、ユーザー認証をapi.phpに追加してください。それ以外の場合は、そのファイルへのパスを知っているすべての人がファイルをバケットにアップロードできます。
credentials.inc.php:
<?php
return array(
'includes' => array('_aws'),
'services' => array(
'default_settings' => array(
'params' => array(
'key' => 'MY-ACCESS-KEY',
'secret' => 'MY-SECRECT',
'region' => 'eu-west-1' // set to your region
)
)
)
);
client.js:
$("input[type=file]").onchange = function () {
for (var file, i = 0; i < this.files.length; i++) {
file = this.files[i];
$.ajax({
url : s3presignedApiUri,
data: 'file='+ file.name + '&mime=' + file.type,
type : "GET",
dataType : "json",
cache : false,
})
.done(function(s3presignedUrl) {
$.ajax({
url : s3presignedUrl,
type : "PUT",
data : file,
dataType : "text",
cache : false,
contentType : file.type,
processData : false
})
.done(function(){
console.info('YEAH', s3presignedUrl.split('?')[0].substr(6));
}
.fail(function(){
console.error('damn...');
}
})
}
};
s3 cors設定(PUT&OPTIONSは実際に必要ですが、OPTIONSを直接有効にすることはできません...):
<?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>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
JQueryを使用していない場合、これはフロントエンドで必要な最小限のものです。
var xhr = new XMLHttpRequest();
xhr.open('PUT', signedUrl, true);
xhr.setRequestHeader('Content-Type', signedUrlContentType);
xhr.onload = () => {
if (xhr.status === 200) {
// success!
}
};
xhr.onerror = () => {
// error...
};
xhr.send(file); // `file` is a File object here
Fileオブジェクトのドキュメントを参照してください: https://developer.mozilla.org/en-US/docs/Web/API/File
その後、通常どおりアップロードの進行状況を追加できます。
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
var percent = Math.round((event.loaded / event.total) * 100)
console.log(percent);
}
};
プロジェクトでは、現在作業しているものについて、クライアントから直接S3にファイルをアップロードしています。私の場合は、いくつかの手順で機能します。
それからの主要なコード部分があります: https://Gist.github.com/zxbodya/3cdabd9172bcc89f8ac5
ACL
とContentType
を追加してください、それが動作するようになります。
const param = {
Bucket: 'Bucket',
Key: 'fiileName',
ACL: 'public-read',
ContentType: 'fileType'
};
s3.getSignedUrl('putObject', param, function (err, url) {
console.log('The URL is', url);
});
私はgithubを介したこのよりクリーンなアプローチを好みます:
ブラウザー用に事前に署名されたURLが既に生成されている場合は、そのURLとペイロードを使用してXHRリクエストを送信するだけで、S3にアップロードできます。 SDKはこれを行う必要はありません。以下のjQueryの例:
$.ajax({
url: presignedUrl, // the presigned URL
type: 'PUT',
data: 'data to upload into URL',
success: function() { console.log('Uploaded data successfully.'); }
});
2つのアプローチを提案できます。
1- 1つの資格情報を使用して、アプリで事前署名済みフォームを生成できます
ドキュメントを参照してください: http://docs.aws.Amazon.com/AmazonS3/latest/dev/HTTPPOSTForms.html
2- Web IDフェデレーションを使用し、Google、FacebookまたはAmazonでログインを使用できます。
ドキュメントを参照してください: http://docs.aws.Amazon.com/AWSJavaScriptSDK/guide/browser-configuring-wif.html
遊び場: http://aws.typepad.com/aws/2013/08/the-aws-web-identity-federation-playground.html