我需要从Angular 2快速入门基础上传angular.io(他们不使用webpack)
这是组件中的代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toast_container"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
>
<RelativeLayout
android:layout_width="800dp"
android:layout_height="wrap_content"
android:background="@drawable/toast_bg">
<ImageView
android:id="@+id/toastIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@drawable/toast_icon" />
<TextView
android:id="@+id/toastMsg"
android:layout_toRightOf="@+id/toastIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="sample toast message"/>
</RelativeLayout>
}
以下是Firefox Web控制台中的错误日志:
有一个错误:对象{__zone_symbol__error:错误,fileName:Getter,lineNumber:Getter,columnNumber:Getter,message:Getter,stack:Getter,originalStack:Getter,zoneAwareStack:Getter,toString:createMethodProperty / props [key] .value(),toSource:createMethodProperty / props [key] .value(),7 more ...}
适用于Chrome:
XMLHttpRequest无法加载http://bucketname.s3.amazonaws.com/categories/imagename.png。对预检请求的响应没有通过访问控制检查:否&#39;访问控制 - 允许 - 来源&#39;标头出现在请求的资源上。起源&#39; localhost:3000&#39;因此不允许访问。响应的HTTP状态代码为400。
正如我刚刚学习的那样,我正在尝试一个宽松的CORS:
@Injectable()
export class S3Service {
private uploadSuccess = true;
private creds = {
"bucket": "nameOfBucket",
"access_key": "accessKey",
"secret_key": "secretKey",
"region": "us-east-1"
}
upload(file: File){
if (file){
console.log('verified with file');
}else{
console.log('without file');
}
console.log('filetype verified as images/png: ', file.type);
AWS.config.update({
accessKeyId: this.creds.access_key,
secretAccessKey: this.creds.secret_key,
});
AWS.config.region = this.creds.region;
AWS.config.sslEnabled = false;
console.log('aws.s3 is verified to be a function: ', AWS.S3);
let bucket = new AWS.S3({ params: { Bucket: this.creds.bucket }});
let key = `categories/${file.name}`;
console.log('verified key is : ', key);
let params = {Key: key, Body: file, ContentType: file.type, ServerSideEncryption: 'AES256'};
bucket.putObject(params, function (err: Response | any, data: Response) {
if (err){
console.log('there is an error: ', err);
}
else{
console.log('there is no error in s3 upload');
}
});
Angular 1代码成功上传图像。
请帮助和高级谢谢。
答案 0 :(得分:3)
S3存储桶上的CORS配置在您描述的方案中看起来很好。
我认为问题出在您的代码产生的端点URL上。我有一个类似的问题,它很混乱,很难追查。
出于某种原因,AWS SDK似乎会根据您用于设置区域信息和/或存储桶名称的方法生成不同的端点URL。如果生成的URL不包含区域信息(您的URL没有),则会导致飞行前请求失败,从而导致浏览器控制台中有关CORS的错误消息(有时可能是预检失败的根源。)
&#39;问题&#39;端点格式:http(s)://<bucketname>.s3.amazonaws.com/<key>
&#39;期望&#39;端点格式:http(s)://s3-<region>.amazonaws.com/<bucketname>/<key>
尝试使用此处提供的组件来验证您的AWS S3配置,访问权限和CORS设置。然后,如果您愿意,可以轻松地将S3特定内容提取到服务中。
以下是步骤:
<s3-upload-test></s3-upload-test>
)(请参阅下面的app.component.ts)。<强> S3-上传-test.component.ts:强>
import { Component } from '@angular/core';
import { Credentials, S3 } from 'aws-sdk';
@Component({
selector: 's3-upload-test',
template: `
<div class="uploadSection">
<hr>
<h3>S3 File Upload Test</h3>
<div class="subsection">
<h4>Confirm Endpoint Format:</h4>
<div class="indent">
The endpoint should be in the following format <span class="monospace">s3-<region>.amazonaws.com</span>.
<pre>
Based on the configuration information you provided:
Expect Endpoint: {{expectEndpoint}}
Actual Endpoint: {{actualEndpoint}}
</pre>
</div>
</div>
<div class="subsection">
<h4>Select File:</h4>
<div class="indent">
<input type="file" (change)="fileEvent($event)" />
</div>
</div>
<div class="subsection">
<h4>Upload Status/Results:</h4>
<div class="indent">
<span class="monospace result">{{uploadStatus}}</span>
</div>
</div>
<hr>
</div>
`,
styles: [`
.uploadSection { font-family: sans-serif; }
.monospace { font-family: monospace; }
.subsection { margin-top: 35px;}
.indent { margin-left: 20px;}
.result { background-color: lightyellow }
`]
})
export class S3UploadTestComponent {
// Replace the values with your own
private readonly _awsConfig = {
accessKeyId: "<your keyId>",
secretAccessKey: "<your secret>",
s3BucketRegion: "<your region>", // example: "us-west-2"
s3BucketName: "<your bucket>" // example: "mycompany.testbucket"
}
private _awsCredentials: Credentials;
private _s3ClientConfig: S3.ClientConfiguration;
private _s3: S3;
uploadStatus: string = "(no upload yet)";
expectEndpoint: string;
actualEndpoint: string;
constructor() {
// Create an AWS S3 client
this._awsCredentials = new Credentials(this._awsConfig.accessKeyId, this._awsConfig.secretAccessKey);
this._s3ClientConfig = {
credentials: this._awsCredentials,
region: this._awsConfig.s3BucketRegion,
sslEnabled: true
};
this._s3 = new S3(this._s3ClientConfig);
// Set the expected and actual endpoints
var isRegionUSEast :boolean = (this._awsConfig.s3BucketRegion).toLowerCase() == "us-east-1";
var endpointHost :string = isRegionUSEast ? "s3" : "s3-" + this._awsConfig.s3BucketRegion
this.expectEndpoint = endpointHost + ".amazonaws.com";
this.actualEndpoint = this._s3.config.endpoint;
}
// Event triggered when a file has been specified
fileEvent(fileInput: any) {
this.uploadStatus = "starting upload...";
// get the file to upload
let file: File = fileInput.target.files[0];
console.log(file);
// upload file to S3
let putObjectRequest: S3.PutObjectRequest = {
Key: 'categories/' + file.name,
Body: file,
Bucket: this._awsConfig.s3BucketName,
ContentType: file.type,
ServerSideEncryption: "AES256"
};
// use "that" to be able to reach component properties within the then/catch callback functions
let that = this;
// upload to S3
this._s3.upload(putObjectRequest).promise()
.then(function (response: S3.ManagedUpload.SendData) {
that.uploadStatus = "Success!\n File URI: " + response.Location;
// alert("upload successful!");
})
.catch(function (err: Error) {
var errMsg = "";
errMsg += "upload failed.\n ";
errMsg += "Error Message: " + err.message + "\n ";
errMsg += "NOTE: an error message of 'Network Failure' may mean that you have the wrong region or the wrong bucket name.";
that.uploadStatus = errMsg;
// alert(errMsg);
});
}
}
systemjs.config.js补充:
(function (global) {
System.config({
...
map: {
...
'aws-sdk': 'npm:aws-sdk'
},
packages: {
...
'aws-sdk': {
defaultExtension: 'js',
main: 'dist/aws-sdk.js',
format: 'global'
}
}
});
})(this);
<强> app.module.ts:强>
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { S3UploadTestComponent } from './s3-upload-test.component';
@NgModule({
imports: [BrowserModule],
declarations: [
AppComponent,
S3UploadTestComponent,
],
bootstrap: [AppComponent]
})
export class AppModule { }
<强> app.component.ts:强>
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1>Hello {{name}}</h1>
<s3-upload-test></s3-upload-test>
`,
})
export class AppComponent { name = 'Angular'; }
AWS S3存储桶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>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
AWS IAM政策(附加到用户或群组):
注意:您几乎肯定希望 使允许的操作更具限制性 ,以满足您的安全需求
注意:将<your bucketname>
替换为适当的值
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1485926968000",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::<your bucketname>/*"
]
}
]
}
如果这不能解决您的问题,请使用Chrome开发工具,然后查看网络&#39;选项卡以查看对S3 API的OPTIONS请求,并使用整个响应更新您的问题。当AWS S3飞行前失败时,它们通常会在响应中提供良好的信息。