我正在尝试将数据上传到AWS S3
。如果我给Content-Type: false
,则会收到错误消息:
At least one of the pre-conditions you specified did not hold</Message><Condition>Bucket POST must be of the enclosure-type multipart/form-data</Condition>
如果我给Content-Type:multipart/form-data
,我会得到一个错误:
The body of your POST request is not well-formed multipart/form-data.
这是我的客户端代码:
const file = document.getElementById('file').files[0];
// let data = e.target;
const filename = file.name;
const contentType = file.type;
const params = [];
const self = this;
$.ajax({
url: self.credentialsUrl,
type: "GET",
dataType: "json",
data: {
filename: filename,
content_type: contentType
},
success: function(s3Data) {
const formData = s3Data.params;
formData["file"] = file;
$.ajax({
type: "POST",
url: s3Data.endpoint_url,
data: formData,
dataType: "xml",
contentType: false,
processData:false,
success: function(resultData){
console.log(resultData);
},
error: function(error){
console.log(error);
}
});
}
});
我在这个问题上坚持了很长时间,任何帮助将不胜感激。
为了生成signature
和policy
,我关注了这个博客:
s3-browser-upload
这是该代码(以防将来不再提供该网址):
var crypto = require('crypto');
// This is the entry function that produces data for the frontend
// config is hash of S3 configuration:
// * bucket
// * region
// * accessKey
// * secretKey
function s3Credentials(config, filename) {
return {
endpoint_url: "https://" + config.bucket + ".s3.amazonaws.com",
params: s3Params(config, filename)
}
}
// Returns the parameters that must be passed to the API call
function s3Params(config, filename) {
var credential = amzCredential(config);
var policy = s3UploadPolicy(config, filename, credential);
var policyBase64 = new Buffer(JSON.stringify(policy)).toString('base64');
return {
key: filename,
acl: 'public-read',
success_action_status: '201',
policy: policyBase64,
'x-amz-algorithm': 'AWS4-HMAC-SHA256',
'x-amz-credential': credential,
'x-amz-date': dateString() + 'T000000Z',
'x-amz-signature': s3UploadSignature(config, policyBase64, credential)
}
}
function dateString() {
var date = new Date().toISOString();
return date.substr(0, 4) + date.substr(5, 2) + date.substr(8, 2);
}
function amzCredential(config) {
return [config.accessKey, dateString(), config.region, 's3/aws4_request'].join('/')
}
// Constructs the policy
function s3UploadPolicy(config, filename, credential) {
return {
// 5 minutes into the future
expiration: new Date((new Date).getTime() + (5 * 60 * 1000)).toISOString(),
conditions: [
{ bucket: config.bucket },
{ key: filename },
{ acl: 'public-read' },
{ success_action_status: "201" },
// Optionally control content type and file size
// {'Content-Type': 'application/pdf'},
['content-length-range', 0, 1000000],
{ 'x-amz-algorithm': 'AWS4-HMAC-SHA256' },
{ 'x-amz-credential': credential },
{ 'x-amz-date': dateString() + 'T000000Z' }
],
}
}
function hmac(key, string) {
var hmac = require('crypto').createHmac('sha256', key);
hmac.end(string);
return hmac.read();
}
// Signs the policy with the credential
function s3UploadSignature(config, policyBase64, credential) {
var dateKey = hmac('AWS4' + config.secretKey, dateString());
var dateRegionKey = hmac(dateKey, config.region);
var dateRegionServiceKey = hmac(dateRegionKey, 's3');
var signingKey = hmac(dateRegionServiceKey, 'aws4_request');
return hmac(signingKey, policyBase64).toString('hex');
}
module.exports = {
s3Credentials: s3Credentials
}