经过三天追逐这个问题。是时候寻求帮助了。 我有一个签名网址将文件上传到Amazon S3。我知道这是正确的,因为
curl -v -T file.png --header "Content-Type:binary/octet-stream" "https://sample.s3.amazonaws.com/33d7e8f0-0fc5-11e5-9d95-2b3410860edd?AWSAccessKeyId=XXXXXXXX&Content-Type=binary%2Foctet-stream&Expires=1433984735&Signature=LUjj8iIAbCfNoskGhqLDhuEWVG4%3D"
正确地成功。
但我的.ajax代码(如下)进行上传会使内容在S3存储桶中略微出现乱码 例如,如果我上传.pdf文件,它会从S3管理控制台正确加载,但如果它是.png或.jpeg等,则会失败...并且密切查看文件的长度(稍微)。
浏览器中呼叫的核心是:
var formData = new FormData();
formData.append("upload", file);
$.ajax({ url: data.puturl,
type: 'PUT',
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
myXhr.upload.addEventListener('progress', progressHandlingFunction,
false);
}
return myXhr;
},
success: completeHandler,
error: errorHandler,
data: formData,
cache: $.param(false),
contentType: "binary/octet-stream",
processData: $.param(false)
}, 'json');
这几乎似乎有效,但数据是乱码。我已经尝试将内容设置为file.type等无济于事。我需要在这里做一些编码吗?比如我失踪的base64 ????
非常感谢任何见解 或者,如果有一种简单的方法可以不使用.ajax做同样的事情,那就太好了。
答案 0 :(得分:1)
从'tedder42'上面提到的问题以及更多实验中,我意识到发送FormData是个问题。所以我将代码更改为只使用FileReader()并传递原始数据。这非常有效。这是代码:
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (e) {
var rawData = reader.result;
$.ajax({ url: data.puturl,
type: 'PUT',
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
}
return myXhr;
},
success: completeHandler,
error: errorHandler,
// Form data
data: rawData,
cache: $.param(false),
contentType: "binary/octet-stream",
processData: $.param(false)
}, 'json');
};
这更简单,一切都很完美。然后,当稍后使用签名的URL下载数据时,我只需输入
ResponseContentDisposition: "attachment; filename="+fileData.name
作为s3.getSignedUrl('getObject',params)调用中的一个参数。
在预先签名的URL中检索文件,我把
ResponseContentDisposition: "attachment; filename="+fileData.name, 'ResponseContentType': fileData.type
负责确保浏览器期望接收的内容。
由于在使用预先签名的URL时上传对象时无法设置内容类型,因此我还在服务器端添加了代码,以便在上载完成后更改对象内容类型。这是代码的核心:
var params = {
Bucket: 'sample',
CopySource: 'sample/' + file.key,
Key: file.key,
MetadataDirective: 'REPLACE',
ContentType: type
};
s3.copyObject(params, function (err, data){
if (err) {
console.log(err);
validationError(res, 'unable to change content-type!');
}
res.sendStatus(200);
});
终于做对了这是一种痛苦,我希望这会有助于其他人!