首页 > 解决方案 > AWS SDK Amazon S3 上传方法破坏图像文件

问题描述

这里的每个人都是我的问题。我用下面的代码写了一个 AWS Lambda:

const AWS = require('aws-sdk');
const S3 = new AWS.S3();

function getValueIgnoringKeyCase(object, key) {
    const foundKey = Object
        .keys(object)
        .find(currentKey => currentKey.toLocaleLowerCase() === key.toLowerCase());
    return object[foundKey];
}

function getBoundary(event) {
    return getValueIgnoringKeyCase(event.headers, 'Content-Type').split('=')[1];
}


module.exports.hello = (event, context, callback) => {
    const boundary = getBoundary(event);
    const result = {};
    event.body
        .split(boundary)
        .forEach(item => {
            if (/filename=".+"/g.test(item)) {
                result[item.match(/name=".+";/g)[0].slice(6, -2)] = {
                    type: 'file',
                    filename: item.match(/filename=".+"/g)[0].slice(10, -1),
                    contentType: item.match(/Content-Type:\s.+/g)[0].slice(14),
                    content: item.slice(item.search(/Content-Type:\s.+/g) + item.match(/Content-Type:\s.+/g)[0].length + 4, -4),
                };
            } else if (/name=".+"/g.test(item)){
                result[item.match(/name=".+"/g)[0].slice(6, -1)] = item.slice(item.search(/name=".+"/g) + item.match(/name=".+"/g)[0].length + 4, -4);
            }
        });

    const response = {
        statusCode: 200,
        body: JSON.stringify(result),
    };

    Promise.all(Object.keys(result)
        .filter(item => result[item].type === 'file')
        .map(item => (new Promise((resolve, reject) => {
            S3.upload({
                Bucket: 'try753',
                Key: result[item].filename,
                Body: Buffer.from(result[item].content),
            }, (err, data) => {
                if (err) {
                    reject(err);
                }
                console.log(data);
                resolve(data);
            });
        }))))
        .then(() => {
            callback(null, response);
        });


};

在那个函数中,我:

  1. 获取多部分/表单数据
  2. 将数据提取到对象中 3)
  3. 将文件保存到 s3

但这里有一个问题,我得到了一个 50Kb 的图像文件,数据提取后,我得到了 50Kb 的缓冲区,但是当我将文件保存到 s3 时,它的大小是 94Kb 并且被破坏了。在 s3.upload 期间会发生什么?PS 任何媒体文件都有同样的问题。PSS txt 文件没有问题。

标签: amazon-web-servicesamazon-s3file-uploadaws-lambdaaws-sdk

解决方案


要在 API Gateway 中支持二进制负载,您必须通过将媒体类型添加到 RestApi 资源的binaryMediaTypes列表或在IntegrationIntegrationResponse资源上设置contentHandling属性来配置 API 。

根据 contentHandling 值,以及响应的 Content-Type 标头或传入请求的 Accept 标头是否与 binaryMediaTypes 列表中的条目匹配,API Gateway 可以将原始二进制字节编码为 Base64 编码的字符串,解码 Base64 -编码的字符串返回其原始字节,或不加修改地传递正文。

简而言之,根据您的 API Gateway 配置,您的表单数据可能会或可能不会被编码,这需要在您创建 Buffer 时在代码中进行处理。使用第二个参数Buffer.from(string[, encoding])传入相应的编码。

这是内容类型转换表供您参考。

您可以contentHandlingserverless.yml文件中指定与 相同级别的设置integration,例如:

integration: LAMBDA
contentHandling: CONVERT_TO_BINARY

推荐阅读