通过Lambda和API Gateway从AWS S3下载图像 - 使用fetch类

问题描述 投票:0回答:1

我正在尝试使用JavaScript fetch APIAWS API GatewayAWS LambdaAWS 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请求和响应标头:

OPTIONS headers, one of two OPTIONS headers, two of two

这是随后的GET请求和响应标头:

GET headers, one of two GET headers, two of two

对我来说有趣的是,S3控制台中的图像大小报告为699873(没有单位),但是在Chrome中报告的GET事务响应主体大约为2.5 MB(同样没有单位)。

得到的图像是16x16平方和死链接。我在浏览器的控制台或CloudWatch中没有任何错误或警告。

我尝试了很多东西;我很想知道那里的人能想出什么。

提前致谢。

编辑:在Chrome中:

console work showing conversion of fetch response to text representing a JSON-encoded Buffer

amazon-s3 aws-lambda aws-api-gateway fetch-api claudiajs
1个回答
0
投票

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;
© www.soinside.com 2019 - 2024. All rights reserved.