nbp*_*pp2 10 amazon-s3 cors angularjs
所以我在将文件直接上传到S3时遇到了一些麻烦.目前我的流程是向nodejs/express发出请求以获取签名的URL.
app.post('/s3SignedURL', function(req, res){
var id = crypto.randomBytes(20).toString('hex');
var ext = path.extname(req.body.fileName);
var unambFilename = path.basename(req.body.fileName, ext) + '-' + id + ext;
var params = {Bucket: awsBucket, Key: unambFilename, Expires: 30};
var signedUrl = s3.getSignedUrl('putObject', params);
res.send({signedUrl: signedUrl, s3FileName: unambFilename});
});
Run Code Online (Sandbox Code Playgroud)
我的角度控制器然后尝试使用该签名URL直接上传到s3($ scope.uploadDocument())
flqApp.controller('DocUploadModalCtrl', ['$scope', '$http', 'customProvider', 'custom',
function($scope, $http, customProvider, custom){
$scope.fileTypes =
[
"Type 1",
"Type 2"
]
$scope.setFile = function(element){
$scope.$apply(function($scope){
$scope.currentDocument = element.files[0];
});
}
$scope.uploadDocument = function() {
$http.post('/s3SignedURL', {fileName: $scope.currentDocument.name} )
.success(function(results){
$http.put(results.signedUrl, $scope.currentDocument)
.success(function(){
custom.document = s3FileName;
customProvider.save(custom, function(){
//..do something here
});
});
});
};
}]);
Run Code Online (Sandbox Code Playgroud)
我的HTML表单看起来像
<form ng-submit="uploadDocument()">
<label for="documentType">File Type</label>
<select class="form-control" ng-model="docType" ng-options="type for type in fileTypes" required >
<option value=""/>
</select>
<label for="filename">Choose file to upload</label>
<input type="file"
name="s3File"
onchange="angular.element(this).scope().setFile(this)"
ng-model="fileName"
required />
<input type="submit" value="Upload File">
</form>
Run Code Online (Sandbox Code Playgroud)
但是每当我尝试上传到S3时,我都会收到错误消息
Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin
Run Code Online (Sandbox Code Playgroud)
我知道S3 CORS在亚马逊端正确设置,因为我开发了使用相同存储桶进行开发存储的ruby应用程序.(因为我正在使用回形针和雾).其次,由于亚马逊回应没有失败,我不怀疑错误来自那里.但它确实来自我尝试将文件放在亚马逊上的行.
所以我确信我错过了一些东西,但我认为使用签名的URL我不需要做任何东西,只需要把它放到那个网址上.
我一直在努力解决这个问题,最后弄明白了!我将详细说明我的步骤,希望它可以帮助一些人.
我使用了这个模块:https://github.com/asafdav/ng-s3upload
我按照他们列出的步骤,即:
添加CORS配置:
<?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>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
Run Code Online (Sandbox Code Playgroud)
将"crossdomain.xml"添加到存储桶的根目录,使其公开
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" secure="false" />
</cross-domain-policy>
Run Code Online (Sandbox Code Playgroud)创建一个将返回JSON的服务,其中包含以下内容:
{
"policy":"XXX",
"signature":"YYY",
"key":"ZZZ"
}
Run Code Online (Sandbox Code Playgroud)这是最重要的一步:确保生成正确的策略文档.
这是我在C#中的代码
StringBuilder builder = new StringBuilder();
builder.Append("{")
.Append("\"expiration\": \"")
.Append(GetFormattedTimestamp(expireInMinutes))
.Append("\",")
.Append("\"conditions\": [")
.Append("{\"bucket\": \"")
.Append(bucketName)
.Append("\"},")
.Append("{\"acl\": \"")
.Append("public-read")
.Append("\"},")
.Append("[\"starts-with\", \"$key\", \"")
.Append(prefix)
.Append("\"],")
.Append("[\"starts-with\", \"$Content-Type\", \"\"],")
.Append("[ \"content-length-range\", 0, " + 10 * 1024 * 1024 + "]")
.Append("]}");
Encoding encoding = new UTF8Encoding();
this.policyString = Convert.ToBase64String(encoding.GetBytes(builder.ToString().ToCharArray()));
this.policySignature = SignPolicy(awsSecretKey, policyString);
Run Code Online (Sandbox Code Playgroud)
这会生成以下Json
{
"expiration":"2014-02-13T15:17:40.998Z",
"conditions":[
{
"bucket":"bucketusaa"
},
{
"acl":"public-read"
},
[
"starts-with",
"$key",
""
],
[
"starts-with",
"$Content-Type",
""
],
[
"content-length-range",
0,
10485760
]
]
}
Run Code Online (Sandbox Code Playgroud)
然后对该文档进行base64编码并作为字符串向下发送.
我的问题在于我的政策文件.策略文档就像您为会话定义的一组规则,例如:文件名必须以某些东西开头(即上传到子文件夹),大小必须在范围内.
使用浏览器的开发人员工具,看一下网络选项卡,看看AWS正在返回哪些错误,这对我有帮助,它会说出政策错误等内容,并说明哪些条件失败了.您通常会获得访问被拒绝的错误,这将基于策略文档中设置的条件或错误的密钥.
另外一些浏览器与localhost CORS有问题.但使用上面的我能够使用chrome从我的本地开发机器上传文件.
Access-Control-Allow-Origin不允许使用origin"localhost:3000"
从您的错误看,您似乎没有在AWS端设置CORS规则.
这个例子可能会有所帮助:https : //github.com/bookingbricks/file-upload-example 使用:Node, aws-sdk-js, jQuery-file-upload (blueimp)
服务器:
var AWS = require('aws-sdk');
AWS.config.update({accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY});
AWS.config.region = 'eu-west-1';
app.post('/s', function (req, res) {
var s3 = new AWS.S3();
var params = {Bucket: 'BUCKETNAME', Key: req.body.name, ContentType: req.body.type};
s3.getSignedUrl('putObject', params, function(err, url) {
if(err) console.log(err);
res.json({url: url});
});
});
Run Code Online (Sandbox Code Playgroud)
客户:
$.ajax({
url: '/s',
type: 'POST',
data: {name: file.name, size: file.size, type:file.type},
}).success(function(res){
$.ajax({
url: res.url,
type: 'PUT',
data: file,
processData: false,
contentType: file.type,
}).success(function(res){
console.log('Done');
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9130 次 |
最近记录: |