我认为你想要的是使用POST进行基于浏览器的上传。
基本上,你需要服务器端代码来生成签名策略。一旦客户端拿到了签名策略,它就可以直接使用POST将数据上传到S3而不必通过你的服务器传输数据。
这里是官方文档链接:
图示:http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html
示例代码:http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTExamples.html
签名策略会以以下形式出现在你的html表单中:
<html>
<head>
...
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
...
</head>
<body>
...
<form action="http://johnsmith.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
Key to upload: <input type="input" name="key" value="user/eric/" /><br />
<input type="hidden" name="acl" value="public-read" />
<input type="hidden" name="success_action_redirect" value="http://johnsmith.s3.amazonaws.com/successful_upload.html" />
Content-Type: <input type="input" name="Content-Type" value="image/jpeg" /><br />
<input type="hidden" name="x-amz-meta-uuid" value="14365123651274" />
Tags for File: <input type="input" name="x-amz-meta-tag" value="" /><br />
<input type="hidden" name="AWSAccessKeyId" value="AKIAIOSFODNN7EXAMPLE" />
<input type="hidden" name="Policy" value="POLICY" />
<input type="hidden" name="Signature" value="SIGNATURE" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
...
</html>
注意,FORM操作直接将文件发送到S3,而不是通过您的服务器。
每当您的用户想要上传文件时,您都会在服务器上创建POLICY和SIGNATURE。然后将页面返回给用户的浏览器。用户可以直接上传文件到S3,而无需通过您的服务器。
签署策略时,通常会使策略在几分钟后过期。这迫使您的用户在上传之前与服务器通信。如果需要,这让您监视和限制上传。
唯一传输到或从您的服务器的数据是已签名的URL。您的秘密密钥保留在服务器上。
${filename}
加入到键名中,对于上面的例子,应该是 user/eric/${filename}
而不是只有 user/eric
。如果 user/eric
已经存在作为一个文件夹,上传会默默地失败(你甚至会被重定向到成功操作重定向页面),上传的内容也不会存在其中。刚刚我花了几个小时来调试,以为这是一个权限问题。 - Balint Erdi<!DOCTYPE html>
<html>
<head>
<title>AWS S3 File Upload</title>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js"></script>
</head>
<body>
<input type="file" id="file-chooser" />
<button id="upload-button">Upload to S3</button>
<div id="results"></div>
<script type="text/javascript">
AWS.config.region = 'your-region'; // 1. Enter your region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'your-IdentityPoolId' // 2. Enter your identity pool
});
AWS.config.credentials.get(function(err) {
if (err) alert(err);
console.log(AWS.config.credentials);
});
var bucketName = 'your-bucket'; // Enter your bucket name
var bucket = new AWS.S3({
params: {
Bucket: bucketName
}
});
var fileChooser = document.getElementById('file-chooser');
var button = document.getElementById('upload-button');
var results = document.getElementById('results');
button.addEventListener('click', function() {
var file = fileChooser.files[0];
if (file) {
results.innerHTML = '';
var objKey = 'testing/' + file.name;
var params = {
Key: objKey,
ContentType: file.type,
Body: file,
ACL: 'public-read'
};
bucket.putObject(params, function(err, data) {
if (err) {
results.innerHTML = 'ERROR: ' + err;
} else {
listObjs();
}
});
} else {
results.innerHTML = 'Nothing to upload.';
}
}, false);
function listObjs() {
var prefix = 'testing';
bucket.listObjects({
Prefix: prefix
}, function(err, data) {
if (err) {
results.innerHTML = 'ERROR: ' + err;
} else {
var objKeys = "";
data.Contents.forEach(function(obj) {
objKeys += obj.Key + "<br>";
});
results.innerHTML = objKeys;
}
});
}
</script>
</body>
</html>
在已经接受的答案中添加更多信息,您可以参考我的博客查看使用AWS Signature版本4的代码运行版本。
这里是总结:
用户选择要上传的文件后,立即执行以下操作: 1. 调用Web服务器以启动生成所需参数的服务
在此服务中,调用AWS IAM服务以获取临时凭证
拥有凭证后,创建一个Bucket Policy(Base64编码字符串)。 然后使用临时秘密访问密钥对Bucket Policy进行签名以生成最终签名
将必要的参数发送回UI
一旦接收到此内容,请创建一个HTML表单对象,设置所需的参数并进行POST操作。
有关详细信息,请参见 https://wordpress1763.wordpress.com/2016/10/03/browser-based-upload-aws-signature-version-4/
我提供了一个简单的代码,用于从Javascript浏览器上传文件到AWS S3并列出S3存储桶中的所有文件。
步骤:
To know how to create Create IdentityPoolId http://docs.aws.amazon.com/cognito/latest/developerguide/identity-pools.html
Goto S3's console page and open cors configuration from bucket properties and write following XML code into that.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Create HTML file containing following code change the credentials, open file in browser and enjoy.
<script type="text/javascript">
AWS.config.region = 'ap-north-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'ap-north-1:*****-*****',
});
var bucket = new AWS.S3({
params: {
Bucket: 'MyBucket'
}
});
var fileChooser = document.getElementById('file-chooser');
var button = document.getElementById('upload-button');
var results = document.getElementById('results');
function upload() {
var file = fileChooser.files[0];
console.log(file.name);
if (file) {
results.innerHTML = '';
var params = {
Key: n + '.pdf',
ContentType: file.type,
Body: file
};
bucket.upload(params, function(err, data) {
results.innerHTML = err ? 'ERROR!' : 'UPLOADED.';
});
} else {
results.innerHTML = 'Nothing to upload.';
} }
</script>
<body>
<input type="file" id="file-chooser" />
<input type="button" onclick="upload()" value="Upload to S3">
<div id="results"></div>
</body>
以下是使用Node和Serverless生成策略文档的方法。
"use strict";
const uniqid = require('uniqid');
const crypto = require('crypto');
class Token {
/**
* @param {Object} config SSM Parameter store JSON config
*/
constructor(config) {
// Ensure some required properties are set in the SSM configuration object
this.constructor._validateConfig(config);
this.region = config.region; // AWS region e.g. us-west-2
this.bucket = config.bucket; // Bucket name only
this.bucketAcl = config.bucketAcl; // Bucket access policy [private, public-read]
this.accessKey = config.accessKey; // Access key
this.secretKey = config.secretKey; // Access key secret
// Create a really unique videoKey, with folder prefix
this.key = uniqid() + uniqid.process();
// The policy requires the date to be this format e.g. 20181109
const date = new Date().toISOString();
this.dateString = date.substr(0, 4) + date.substr(5, 2) + date.substr(8, 2);
// The number of minutes the policy will need to be used by before it expires
this.policyExpireMinutes = 15;
// HMAC encryption algorithm used to encrypt everything in the request
this.encryptionAlgorithm = 'sha256';
// Client uses encryption algorithm key while making request to S3
this.clientEncryptionAlgorithm = 'AWS4-HMAC-SHA256';
}
/**
* Returns the parameters that FE will use to directly upload to s3
*
* @returns {Object}
*/
getS3FormParameters() {
const credentialPath = this._amazonCredentialPath();
const policy = this._s3UploadPolicy(credentialPath);
const policyBase64 = new Buffer(JSON.stringify(policy)).toString('base64');
const signature = this._s3UploadSignature(policyBase64);
return {
'key': this.key,
'acl': this.bucketAcl,
'success_action_status': '201',
'policy': policyBase64,
'endpoint': "https://" + this.bucket + ".s3-accelerate.amazonaws.com",
'x-amz-algorithm': this.clientEncryptionAlgorithm,
'x-amz-credential': credentialPath,
'x-amz-date': this.dateString + 'T000000Z',
'x-amz-signature': signature
}
}
/**
* Ensure all required properties are set in SSM Parameter Store Config
*
* @param {Object} config
* @private
*/
static _validateConfig(config) {
if (!config.hasOwnProperty('bucket')) {
throw "'bucket' is required in SSM Parameter Store Config";
}
if (!config.hasOwnProperty('region')) {
throw "'region' is required in SSM Parameter Store Config";
}
if (!config.hasOwnProperty('accessKey')) {
throw "'accessKey' is required in SSM Parameter Store Config";
}
if (!config.hasOwnProperty('secretKey')) {
throw "'secretKey' is required in SSM Parameter Store Config";
}
}
/**
* Create a special string called a credentials path used in constructing an upload policy
*
* @returns {String}
* @private
*/
_amazonCredentialPath() {
return this.accessKey + '/' + this.dateString + '/' + this.region + '/s3/aws4_request';
}
/**
* Create an upload policy
*
* @param {String} credentialPath
*
* @returns {{expiration: string, conditions: *[]}}
* @private
*/
_s3UploadPolicy(credentialPath) {
return {
expiration: this._getPolicyExpirationISODate(),
conditions: [
{bucket: this.bucket},
{key: this.key},
{acl: this.bucketAcl},
{success_action_status: "201"},
{'x-amz-algorithm': 'AWS4-HMAC-SHA256'},
{'x-amz-credential': credentialPath},
{'x-amz-date': this.dateString + 'T000000Z'}
],
}
}
/**
* ISO formatted date string of when the policy will expire
*
* @returns {String}
* @private
*/
_getPolicyExpirationISODate() {
return new Date((new Date).getTime() + (this.policyExpireMinutes * 60 * 1000)).toISOString();
}
/**
* HMAC encode a string by a given key
*
* @param {String} key
* @param {String} string
*
* @returns {String}
* @private
*/
_encryptHmac(key, string) {
const hmac = crypto.createHmac(
this.encryptionAlgorithm, key
);
hmac.end(string);
return hmac.read();
}
/**
* Create an upload signature from provided params
* https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html#signing-request-intro
*
* @param policyBase64
*
* @returns {String}
* @private
*/
_s3UploadSignature(policyBase64) {
const dateKey = this._encryptHmac('AWS4' + this.secretKey, this.dateString);
const dateRegionKey = this._encryptHmac(dateKey, this.region);
const dateRegionServiceKey = this._encryptHmac(dateRegionKey, 's3');
const signingKey = this._encryptHmac(dateRegionServiceKey, 'aws4_request');
return this._encryptHmac(signingKey, policyBase64).toString('hex');
}
}
module.exports = Token;
{
"bucket": "my-bucket-name",
"region": "us-west-2",
"bucketAcl": "private",
"accessKey": "MY_ACCESS_KEY",
"secretKey": "MY_SECRET_ACCESS_KEY",
}
我基于VueJS和Go创建了一个UI,用于上传二进制文件到AWS Secrets Manager https://github.com/ledongthuc/awssecretsmanagerui
这对于上传安全文件和更新文本数据非常有帮助。如果需要,您可以参考一下。