我正在尝试使用JavaScript fetch API,AWS API Gateway,AWS Lambda和AWS S3来创建一项允许用户上传和下载媒体的服务。服务器正在使用NodeJs 8.10;浏览器是Google Chrome版本69.0.3497.92(官方版本)(64位)。
从长远来看,允许的媒体将包括音频,视频和图像。现在,我很乐意让图像工作。
我遇到的问题是:我的浏览器端客户端,使用fetch实现,能够通过API网关和Lambda将JPEG上传到S3。我可以使用curl
或S3控制台从我的S3存储桶下载JPEG,然后在图像查看器中查看图像就好了。
但是,如果我尝试通过浏览器端客户端下载图像并获取,我无法在浏览器中显示任何内容。
这是来自浏览器端客户端的代码:
fetch(
'path/to/resource',
{
method: 'post',
mode: "cors",
body: an_instance_of_file_from_an_html_file_input_tag,
headers: {
Authorization: user_credentials,
'Content-Type': 'image/jpeg',
},
}
).then((response) => {
return response.blob();
}).then((blob) => {
const img = new Image();
img.src = URL.createObjectURL(blob);
document.body.appendChild(img);
}).catch((error) => {
console.error('upload failed',error);
});
这是服务器端代码,使用Claudia.js:
const AWS = require('aws-sdk');
const ApiBuilder = require('claudia-api-builder');
const api = new ApiBuilder();
api.corsOrigin(allowed_origin);
api.registerAuthorizer('my authorizer', {
providerARNs: ['arn of my cognito user pool']
});
api.get(
'/media',
(request) => {
'use strict';
const s3 = new AWS.S3();
const params = {
Bucket: 'name of my bucket',
Key: 'name of an object that is confirmed to exist in the bucket and to be properly encoded as and readable as a JPEG',
};
return s3.getObject(params).promise().then((response) => {
return response.Body;
})
;
}
);
module.exports = api;
以下是Chrome网络面板中的初始OPTION
请求和响应标头:
这是随后的GET
请求和响应标头:
对我来说有趣的是,S3控制台中的图像大小报告为699873(没有单位),但是在Chrome中报告的GET事务响应主体大约为2.5 MB(同样没有单位)。
得到的图像是16x16平方和死链接。我在浏览器的控制台或CloudWatch中没有任何错误或警告。
我尝试了很多东西;我很想知道那里的人能想出什么。
提前致谢。
编辑:在Chrome中:
Claudia要求客户端指定它将在二进制有效负载上接受哪种MIME类型。所以,将'Content-type'
配置保存在headers
对象的客户端:
fetch(
'path/to/resource',
{
method: 'post',
mode: "cors",
body: an_instance_of_file_from_an_html_file_input_tag,
headers: {
Authorization: user_credentials,
'Content-Type': 'image/jpeg', // <-- This is important.
},
}
).then((response) => {
return response.blob();
}).then((blob) => {
const img = new Image();
img.src = URL.createObjectURL(blob);
document.body.appendChild(img);
}).catch((error) => {
console.error('upload failed',error);
});
然后,在服务器端,您需要告诉Claudia响应应该是二进制的以及要使用的MIME类型:
const AWS = require('aws-sdk');
const ApiBuilder = require('claudia-api-builder');
const api = new ApiBuilder();
api.corsOrigin(allowed_origin);
api.registerAuthorizer('my authorizer', {
providerARNs: ['arn of my cognito user pool']
});
api.get(
'/media',
(request) => {
'use strict';
const s3 = new AWS.S3();
const params = {
Bucket: 'name of my bucket',
Key: 'name of an object that is confirmed to exist in the bucket and to be properly encoded as and readable as a JPEG',
};
return s3.getObject(params).promise().then((response) => {
return response.Body;
})
;
},
/** Add this. **/
{
success: {
contentType: 'image/jpeg',
contentHandling: 'CONVERT_TO_BINARY',
},
}
);
module.exports = api;