Почему AWS Lambda не загружает изображения на S3 должным образом? - PullRequest
0 голосов
/ 28 февраля 2019

У меня проблема с платформой .NET Core 2.0, связанная с загрузкой файлов изображений в S3 с помощью AWS SDK.

Когда я выполняю POST на своей конечной точке, работающей на локальной IIES, она работает отлично, и яможет увидеть сгенерированный файл в S3 без каких-либо проблем.

Проблема заключается в следующем: после развертывания без сервера на AWS Lambda та же самая конечная точка .NET Core, которая дала отличный результат в моей локальной среде, ведет себя по-разному, когдаон работает на лямбде.

У меня есть основания подозревать, что это не проблема с ролями, политиками или другими проблемами, связанными с разрешениями.

Почему?Ну, во-первых, Lambda действительно загружает файл на S3, он может читать, перечислять и помещать объекты в корзину без каких-либо проблем.

"Тогда в чем проблема?"Вы можете быть удивлены.Проблема заключается в том, что загруженное изображение становится почти в два раза больше оригинала, а содержимое BYT и полностью изменяется после отправки.Даже байты магического числа меняются, я имею в виду те, что находятся в начале файла, представляющего тип файла.

Это результат: Files I uploaded

Первыйодна - это та, которую я загрузил локально, а вторая - это загруженная лямбда-картинка.И да, это одна и та же картина.

Localhost: enter image description here

Lambda: enter image description here На случай, если это вообще поможетВот код C #, реализующий SDK S3:

try
        {
            var region = RegionEndpoint.GetBySystemName(s3Config.Region);
            _s3Client = new AmazonS3Client(region);

            var fileTransferUtility = new TransferUtility(_s3Client);
            using (var memoryStream = new MemoryStream())
            {
                image.CopyTo(memoryStream);

                var fileTransferUtilityRequest = new TransferUtilityUploadRequest
                {
                    InputStream = memoryStream,
                    Key = fileName,
                    BucketName = s3Config.BucketName,
                    CannedACL = S3CannedACL.BucketOwnerFullControl,
                    ContentType = image.ContentType
                };
                await fileTransferUtility.UploadAsync(fileTransferUtilityRequest);
                var link = "http://{0}.s3-{1}.amazonaws.com".FormatWith(s3Config.BucketName, s3Config.Region);
                return ResponseMessages.DocumentUploaded(fileName, link);
            }
        }

Где «изображение» - это переменная IFormFile.Если есть какая-либо другая информация, которую я могу предоставить для устранения этой ошибки, пожалуйста, дайте мне знать.Спасибо.

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Мне жаль, что я пропустил этот вопрос, но короче говоря, вам нужно сообщить API Gateway, что вы собираетесь предоставлять двоичные данные в качестве полезной нагрузки.

Вот иллюстративный пример: enter image description here

Единственное, что вам нужно сделать, - это преобразовать полезную нагрузку в двоичном формате в base64 при загрузке только на S3 (чтоне проблема, потому что ваше приложение получило его в двоичном формате, что сэкономило 33% на размере полезной нагрузки).

Я создал пример NodeJS, так что вам просто нужно изменить егов соответствии с C #:

const upload = body => {
    const id = uuid();
    return new Promise((res, rej) => {
        s3.putObject({
            Bucket: BUCKET,
            Key: id + '.jpg',
            Body: new Buffer(body.replace(/^data:image\/\w+;base64,/, ""),'base64'),
            ContentEncoding: 'base64',
            ContentType: 'image/jpeg'
        }, (err) => {
            if (err) {
                return rej(err);
            }
            return res({
                bucket: BUCKET,
                key: id + '.jpg'
            });
        });
    });
}

Возможно, я немного опоздал на вечеринку, но, надеюсь, это поможет вам понять, в чем проблема.

0 голосов
/ 01 марта 2019

В итоге я использовал SES и SNS для отладки лямбды в реальном времени.Мне буквально пришлось сериализовать объект IFormFile в виде строки и отправить его себе по электронной почте при каждой загрузке изображения.Я также настроил SMS с длиной IFormFile.

На всякий случай это поможет кому-нибудь еще в будущем;дополнительные байты уже были там, как только запрос был обработан.Я имею в виду, что файл размером 29,7 КБ выводил 53000 ~ байтов, поскольку он .Length в первый момент выполнения конечной точки, поэтому это не было лямбда-проблемой (хотя, возможно, это была конфигурация нашего шлюза API или .NET Core).

В любом случае, мы исправили это, ожидая строку base64 как свойство application/json и расшифровывая ее следующим образом:

var imageParts = base64Image.Split(',').ToList();
var buffer = Convert.FromBase64String(imageParts[1]);
await memoryStream.WriteAsync(buffer, 0, buffer.Length);
var fileTransferUtilityRequest = new TransferUtilityUploadRequest
{
    InputStream = memoryStream,
    Key = fileName,
    BucketName = s3Config.BucketName,
    CannedACL = S3CannedACL.BucketOwnerFullControl,
    ContentType = "image/{0}".FormatWith(fileExtension)
};
await fileTransferUtility.UploadAsync(fileTransferUtilityRequest);

Где base64Image - строка в кодировке base64.

Inесли кто-то окажется в том же месте, где мы были вчера, просто проигнорируйте фактическую причину проблемы и используйте Base64, он может быть не таким быстрым, как файл внутри FormBody, но вы наверняка сэкономите некоторое время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...