Загрузка изображений из AWS S3 через Lambda и API Gateway- с использованием класса fetch
Я пытаюсь использовать API извлечения JavaScript, AWS API Gateway, AWS Lambda и AWS S3, чтобы создать сервис, который позволяет пользователям загружать и скачивать мультимедиа. Сервер использует NodeJs 8.10; браузер Google Chrome версии 69.0.3497.92 (официальная сборка) (64-разрядная версия).
В долгосрочной перспективе допустимые носители будут включать аудио, видео и изображения. На данный момент, я был бы рад получить изображения для работы.
Проблема, с которой я сталкиваюсь: мой клиент на стороне браузера, реализованный с использованием fetch, способен нормально загружать JPEG в S3 через API Gateway и Lambda. я могу использовать curl
или Консоль S3, чтобы загрузить JPEG из моей корзины S3, а затем просмотреть изображение в средстве просмотра изображений.
Но, если я пытаюсь загрузить изображение через клиент на стороне браузера и получить его, я не получаю ничего, что я могу отобразить в браузере.
Вот код от клиента на стороне браузера:
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;
Вот начальные OPTION
заголовки запроса и ответа в сетевой панели Chrome:
Вот следствие GET
заголовки запроса и ответа:
Что меня интересует, так это то, что размер изображения сообщается как 699873 (без блоков) в консоли S3, но тело ответа транзакции GET сообщается в Chrome примерно на 2,5 МБ (опять же, без блоков).
Полученное изображение представляет собой квадратное и мертвое звено 16x16. Я не получаю никаких ошибок или предупреждений в консоли браузера или CloudWatch.
Я много чего перепробовал; было бы интересно услышать, что кто-то там может придумать.
Заранее спасибо.
РЕДАКТИРОВАТЬ: В Chrome:
1 ответ
Клаудия требует, чтобы клиент указал, какой тип 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;