如何修正调用WeasyPrint的PHP cURL请求?Laravel应用PDF生成异常排查
问题根源分析
你遇到的问题核心是CMD curl和PHP curl发送请求的格式完全不同:
- 你在CMD里用的
-T参数,是把test.html的内容直接作为POST请求的原始请求体发送,同时设置Content-Type:text/html,Aquavitae的WeasyPrint服务会直接读取这个纯HTML的请求体来生成PDF。 - 而你的PHP代码里用了
curl_file_create配合CURLOPT_POSTFIELDS,这是在模拟multipart/form-data格式的表单文件上传,此时PHP会自动把请求的Content-Type改成multipart/form-data,服务端拿到的不是纯HTML内容,而是表单上传的文件元数据,自然无法正确生成PDF,只会返回你上传的文件相关信息。
解决方案:模拟CMD curl的原始请求体发送
要让PHP curl和CMD的行为一致,你需要直接把HTML文件的内容作为POST请求的body发送,而不是用表单上传的方式。修改后的PHP代码如下:
$path_to_file = 'd:/index.html'; // 读取HTML文件内容 $html_content = file_get_contents($path_to_file); if ($html_content === false) { die("无法读取HTML文件"); } $ch = curl_init(); $headers = array( "Content-Type:text/html" ); // 注意要带上filename参数,和CMD里的URL一致 curl_setopt($ch, CURLOPT_URL, 'http://192.168.99.100:5001/pdf?filename=test.pdf'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // 直接把HTML内容作为POST请求体 curl_setopt($ch, CURLOPT_POSTFIELDS, $html_content); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // 注意:生产环境建议关闭这个,改用正确的SSL证书验证 $result = curl_exec($ch); if (curl_errno($ch)) { echo 'CURL错误:' . curl_error($ch); curl_close($ch); exit; } curl_close($ch); // 将结果保存为PDF文件或者输出到浏览器 // 保存文件 file_put_contents('test.pdf', $result); // 或者在Laravel中直接返回下载响应 // return response($result) // ->header('Content-Type', 'application/pdf') // ->header('Content-Disposition', 'attachment; filename="test.pdf"');
关键细节说明
- 请求体格式:直接传递HTML内容作为POSTFIELDS,确保服务端拿到的是纯text/html格式的原始数据,和CMD curl的行为完全一致。
- URL参数:不要忘记带上
filename=test.pdf的查询参数,和你CMD里的请求保持一致,服务端可能需要这个参数来命名生成的PDF文件。 - 错误处理:添加了文件读取和CURL错误的检查逻辑,方便你快速排查执行过程中出现的问题。
- Laravel适配:如果是在Laravel应用中使用,你可以把最后一步改成返回Laravel的响应,直接让浏览器触发PDF下载,比如代码中注释的部分。
测试验证
运行修改后的代码后,你可以打开生成的test.pdf文件,应该能看到正确渲染的<h1>hello world</h1>内容,和CMD curl生成的PDF完全一致。
内容的提问来源于stack exchange,提问作者Daniil Petrenko
相关产品推荐
相关产品推荐

