首页 > 解决方案 > 使用无服务器、Bref PHP 和 Slim 进行 CORS 或 base64 编码的二进制响应

问题描述

我一直在使用 AWS 设置无服务器(.com)设置,使用Bref(PHP 层)运行MPDF以使用 AWS Lambda 和 API Gateway 将 HTML 转换为 PDF。按照说明,.. 这是设置。

经过大量调试后,看来我可以:

  1. 在无服务器文件中添加apiGateway选项,但我总是遇到 CORS 问题(即经典No 'Access-Control-Allow-Origin' header is present)。我已经尝试了来自客户端/请求端的标头和来自服务器端的响应的每种组合(参见下面的代码)。

  2. 或者,我没有apiGateway选项,如下所示,但是我必须对我的身体进行 base64 编码(请参阅 参考资料$body = base64_encode($pdf);),否则我会收到一个 Bref 错误,说明The Lambda response cannot be encoded to JSON (...) 应该使用这些apiGateway选项。

对正文进行编码很好,但不适用于直接下载,因为我需要data从响应中对它进行 base64decode 以获得二进制数据。

帮助。

serverless.yml :(注意注释掉的 apiGateway 设置 - 阅读更多内容了解原因)

 service: html2pdf
    
    provider:
        name: aws
        region: us-east-1
        runtime: provided
        stage: ${opt:stage, 'dev'}
        # apiGateway:    ## <======= We talk about this below
        #     binaryMediaTypes:
        #         - '*/*'
        # environment:
        #     BREF_BINARY_RESPONSES: 1
    
    plugins:
        - ./vendor/bref/bref
    
    functions:
        html2pdf:
            handler: index.php
            description: ''
            timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
            layers:
                - ${bref:layer.php-73-fpm} #-fpm
            events:
                - http:
                    path: /html2pdf
                    method: post
                    cors: true
    
       
    
    # Exclude files from deployment
    package:
        exclude:
            - 'node_modules/**'
            - 'tests/**'

index.php (在上面的yml 文件中提到):

 <?php
    
    require_once __DIR__ . '/../vendor/autoload.php';
    
    use App\JsonParserMiddleware;
    
    use Psr\Http\Message\ResponseInterface as Response;
    use Psr\Http\Message\ServerRequestInterface as Request;
    use Slim\Factory\AppFactory;
    
    $app = AppFactory::create();
    $app->addMiddleware(new JsonParserMiddleware());
    
    $app->post("/html2pdf", function (Request $request, Response $response) {
        
        $data = $request->getParsedBody();
        $payload = [];
        $statusCode = 200;
        if ($data['data'] == null) {
            $payload['error'] = "HTML 64-bit encoded string is required";
            return response($response, $payload, 422);
        }
        $mpdf = new \Mpdf\Mpdf(['tempDir' => '/tmp']);
        $mpdf->WriteHTML(base64_decode($data['data']));
        
        $pdf = $mpdf->Output(null,"S");
    
        $filename = $data['title'];
    
        $body = base64_encode($pdf);
    
        $response->getBody()->write($body);
    
        $response->isBase64Encoded = true;
        
        $response = $response 
                    ->withHeader("Access-Control-Allow-Origin", "*")
                    ->withHeader('Access-Control-Allow-Credentials', "true")  
                    ->withHeader('Content-Type','application/pdf')
                    ->withHeader('Content-Disposition', sprintf('attachment; filename="%s"', $filename))
                    ->withStatus($statusCode);
        
        return $response;
        
    });

使用 axios 的客户端代码是:

let data = { data: <<some base64 encoded html string>>, title: "file.pdf" };

let options = {
              headers: {
                "Content-Type": "application/json",
                // "Accept": "*/*",
              },
             }
let payload = {data : btoa(data),title:"contract.pdf"};
let url = "https://oli9w0wghb.execute-api.us-east-1.amazonaws.com/dev/html2pdf";

axios.post(url, payload, options)
    .then(response => {
      console.log(response.data);
    });

标签: serverlessbref

解决方案


推荐阅读