我一直在使用 AWS 设置无服务器(.com)设置,使用Bref(PHP 层)运行MPDF以使用 AWS Lambda 和 API Gateway 将 HTML 转换为 PDF。按照说明,.. 这是设置。
经过大量调试后,看来我可以:
在无服务器文件中添加
apiGateway
选项,但我总是遇到 CORS 问题(即经典No 'Access-Control-Allow-Origin' header is present
)。我已经尝试了来自客户端/请求端的标头和来自服务器端的响应的每种组合(参见下面的代码)。或者,我没有
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);
});