You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Micronaut创建返回二进制内容的AWS Lambda函数

Micronaut Lambda + API Gateway 返回PDF文件解决方案

没问题,这种场景完全是支持的!你遇到的Content-Type始终是application/json的问题,主要是因为API Gateway未配置二进制媒体类型,再加上Micronaut默认会把byte[]序列化成JSON数组导致的。结合你用Groovy+Dynamic Reports+DynamoDB的需求,下面给你一步步梳理解决步骤:

一、先配置AWS API Gateway支持二进制PDF

API Gateway默认只会把application/json等少数类型当作文本处理,要返回PDF必须先添加对应的二进制媒体类型:

  • 如果你用的是REST API(API Gateway v1):
    1. 登录AWS控制台,进入API Gateway服务,找到你的目标API
    2. 切换到「Settings」标签页,在「Binary Media Types」区域点击「Add binary media type」,输入application/pdf后保存
    3. 重新部署你的API(这点很重要,配置变更需要部署才会生效)
  • 如果你用的是HTTP API(API Gateway v2):
    1. 进入目标HTTP API的「Settings」页面
    2. 在「Binary media types」里添加application/pdf
    3. 确保「Payload format version」设置为2.0,这个版本对二进制内容的处理更友好

二、调整Micronaut Groovy代码,正确构建响应

直接返回byte[]时,Micronaut会默认把它序列化成JSON数组,所以我们需要手动构建HTTP响应,指定正确的Content-Type和二进制内容:

import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import net.sf.dynamicreports.jasper.builder.JasperReportBuilder
import static net.sf.dynamicreports.report.builder.DynamicReports.*

@Controller("/reports")
class PdfReportController {

    @Get("/download")
    HttpResponse<byte[]> generatePdfReport() {
        // 1. 从DynamoDB获取数据(这里替换成你的实际查询逻辑)
        def reportData = fetchDataFromDynamoDB()

        // 2. 用Dynamic Reports生成PDF字节数组
        byte[] pdfBytes = buildPdfReport(reportData)

        // 3. 构建正确的HTTP响应
        return HttpResponse.ok(pdfBytes)
                .contentType("application/pdf")
                // 可选:添加Content-Disposition,让浏览器直接下载或预览
                .header("Content-Disposition", "inline; filename=dynamodb-report.pdf")
    }

    private List<Map<String, Object>> fetchDataFromDynamoDB() {
        // 你的DynamoDB数据查询逻辑,比如用AWS SDK for Groovy
        // 示例伪代码:
        // def dynamoDb = AmazonDynamoDBClientBuilder.defaultClient()
        // def scanResult = dynamoDb.scan(new ScanRequest().withTableName("YourTable"))
        // return scanResult.items
        [] // 替换成实际数据
    }

    private byte[] buildPdfReport(List<Map<String, Object>> data) {
        def outputStream = new ByteArrayOutputStream()
        JasperReportBuilder report = report()
                .columns(
                    col.column("ID", "id", type.stringType()),
                    col.column("Name", "name", type.stringType())
                    // 根据你的数据添加更多列
                )
                .title(cmp.text("DynamoDB Data Report"))
                .pageFooter(cmp.pageXofY())
                .setDataSource(data)
        
        report.toPdf(outputStream)
        return outputStream.toByteArray()
    }
}

三、Lambda Handler配置确认

确保你的Lambda函数使用Micronaut官方的Lambda代理适配器,即把handler设置为:

io.micronaut.function.aws.proxy.MicronautLambdaHandler

这个适配器会正确处理Micronaut的HTTP响应,并把二进制内容传递给API Gateway。

额外注意事项

  • 如果用Serverless Framework或AWS SAM部署,记得在部署模板里配置二进制媒体类型,比如SAM模板示例:
Resources:
  PdfReportApi:
    Type: AWS::Serverless::Api
    Properties:
      BinaryMediaTypes:
        - application/pdf
      StageName: prod
  PdfReportFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: io.micronaut.function.aws.proxy.MicronautLambdaHandler
      Runtime: java17 # 对应你的Micronaut支持的Java版本
      Events:
        ApiEvent:
          Type: Api
          Properties:
            RestApiId: !Ref PdfReportApi
            Path: /reports/download
            Method: get
  • 测试时,确保请求的Accept头设置为application/pdf,这样API Gateway会直接返回二进制PDF,而不是Base64编码的字符串
  • 本地测试时,可以先单独验证Dynamic Reports生成的PDF字节数组是否正确,比如保存到本地文件打开确认

内容的提问来源于stack exchange,提问作者J. Snook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:42:04