Trying to stream s3 image to http response via lambda function URL

0

Hello,

I'm new to using AWS Lambda to stream HTTP responses. I am using typescript, node.js, and Lambda function URL and am building a Lambda application using SAM.

For a small image(less than 6MB), I was able to use "BUFFERED" invokeMode to return the image in the HTTP response. However, for an image bigger than 6MB, I wasn't able to do that as the maximum payload size is 6 MB for that invokeMode.

So, I am trying to stream an image in HTTP response using "STREAM_RESPONSE" invokeMode. I got to a point where the lambda function URL prompts download from the browser, and when I save the response, I can see the streamed image from s3. However, my goal is to stream the image from s3 and display it in the browser when I reach the lambda function URL. What should I do to achieve it? I think my issue is coming from the incorrect content type as the response content type is "application/octet-stream" even though I set my content type to "image/jpeg". Is there a way to prevent manually-set content-type in HTTP response from being overridden to application/octet-stream?

This is the output I see from POSTMAN when I send request to lambda function URL Enter image description here

Here's the code I used:

// lambda function
export const handler: Handler = awslambda.streamifyResponse(async (event, responseStream, context): Promise<any> => {
  let response: any;

  try {
    const s3Uri = `actual-s3-uri`;
    // Log the complete S3 URI
    logger.info({ s3Uri });
  
    // Parse the S3 URI to extract bucket and key
    const { bucket, key } = parseS3Uri(s3Uri);
    logger.info({bucket, key});
    
    const command = new GetObjectCommand({
      Bucket: bucket,
      Key: key,
    });
    const { Body: imageStream, ContentType: contentType, ContentLength } = await s3.send(command);

    if (!imageStream) {
      throw new Error('no body');
    }
    let srcStream;
    // Convert it to a Node.js readable stream
    if (imageStream instanceof Readable) {
        logger.info('imageStream is a readable stream');
        srcStream = imageStream;
    } else if (imageStream instanceof Blob) {
      logger.info('imageStream is a blob');
      const arrayBuffer = await imageStream.arrayBuffer();
      const blobStream = new Readable({
        read() {
          this.push(Buffer.from(arrayBuffer));
          this.push(null);
        }
      });
      srcStream = blobStream;
    } else {
      throw new Error('imageStream is neither a readable stream nor a blob');
    }
    
    logger.info({ contentType, ContentLength});

    // Return the processed image stream directly as the Lambda response
    response = {
      "statusCode": 200,
      "headers": {
        "Content-Type": "image/jpeg"
      },      
      "isBase64Encoded": false,
      "body": await pipeline(srcStream, responseStream), 
    };

    logger.info({statusCode: response.statusCode, headers: response.headers});
    
    return response;
  } catch (err: any) {
    logger.error({ err }, response);
    rollbar.error(err, response, { custom: {} });
    response = {
      statusCode: 500,
      body: JSON.stringify({ message: 'Unexpected error in lambda function' }),
    };
    throw err;
  } finally {
    await promiseRollbarWait(rollbar);
  }
});
Dahwi
질문됨 2달 전467회 조회
1개 답변
0

I hope the URLs listed below will be of use to you.

It seems that you need to pass the header as metadata (JSON) to awslambda.HttpResponseStream.from in order to apply it.

https://repost.aws/ja/questions/QU9MFuTQKOR_WBo-klcQNa7Q/how-do-i-change-status-and-headers-when-streaming-with-lambda-and- function-url

https://github.com/astuyve/lambda-stream

profile picture
전문가
shibata
답변함 한 달 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠