这不是一个完整的答案,但我至少可以帮助您解决有关图像的一些问题,并解释为什么Dompdf 不能与invoice 一起使用。
问题
首先,查看您的代码,您似乎也使用了过时的函数set(..) 并且$options 也没有传递给Dompdf。新的例子可以在the develop branch 中找到,所以我们可以通过以下方式解决第一个问题:
// Include autoloader
require 'vendor/autoload.php';
// reference the Dompdf namespace
$files = glob("/invoices/*.pdf");
foreach ($files as $file) include_once($file);
// Reference the Dompdf namespace
use Dompdf\Dompdf;
//Also reference the options namespace
use Dompdf\Options;
//First initialise the options
$options = new Options();
//This way of setting options is new see: https://github.com/dompdf/dompdf/issues/2181
$options->setIsRemoteEnabled(true);
$options->setDefaultFont('OpenSans');
// Instantiate and use the dompdf class with the options
$dompdf = new Dompdf($options);
// Load content from html file
$html = ...; //file_get_contents("invoice.html");
$dompdf->loadHtml($html);
$dompdf->setPaper('A4', 'portrait'); //landscape / portrait
// Render the HTML as PDF
$dompdf->render();
$output = $dompdf->output();
file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/invoices/" . $order_id . ".pdf", $output);
使用这段代码,我们得到以下结果:
(使用jsFiddle 来防止图像占用太多空间。现在它们是内联的)
<img src="https://i.stack.imgur.com/86xNQ.png" width="600px" />
<img src="https://i.stack.imgur.com/coyyn.png" width="600px" />
这样,至少会呈现徽标。那么还剩下什么?
查看结果,只有部分 html 被正确呈现。所以css文件实际上正在工作。但这里唯一的问题是发票使用flex 等属性,如display: flex 等。然而,这还不被支持,正如 in this GitHub issue 所见。这就是为什么不能正确渲染所有元素的原因。
到目前为止,一种可能的解决方案是使用html2canvas 截取屏幕截图,然后使用jsPdf 将其“转换”为pdf,如in this SO answer 所示。但我不确定这是否适合您的用例。
可能的解决方案
无论如何,从Snappy has no support for flex as well 开始,我已经为这个特定情况创建了一个经过调整的示例,使用html2canvas(确实支持flex)和jsPdf。
首先对例如invoice.php在页面顶部添加以下php函数。这个函数toBase64 会将任何'foreign' svg 转换为本地base64 字符串,可以由html2canvas 处理:
function toBase64($url) {
$data = file_get_contents($url);
$base64 = 'data:image/svg+xml;base64,' . base64_encode($data);
return $base64;
}
要仅制作实际发票的 pdf,请将 id="invoice" 添加到 <div class="card-body p-5 p-md-7 p-lg-11">,这似乎是发票的容器。
要有效使用php功能,请将带有徽标的<img>标签更改为:
<img class="mb-2" src="<?= toBase64('https://streamlabs.nyc3.cdn.digitaloceanspaces.com/assets/svg/logos/logo-short.svg')?>" alt="Logo">
然后像这样更改“打印”按钮的onclick功能:
<button type="button" class="btn btn-info transition-3d-hover" onclick="showPDF();">
<i class="fas fa-print mr-2"></i>
Print
</button>
最后,在页面底部添加这个javascript函数:
function showPDF() {
//Create screenshot of body
html2canvas(document.getElementById('invoice'), {scale: 3,scrollY: -window.scrollY}).then(canvas => {
var imgData = canvas.toDataURL('image/jpeg');
//add the image to, and create the pdf
var pdf = new jsPDF('P', 'pt', [canvas.width, canvas.height]);
pdf.addImage(imgData, 'jpeg', 0, 0, canvas.width, canvas.height);
//set the pdfFinal to be later downloaded
//convert the pdf to a base64 string to make it uploadable
let output = btoa(pdf.output());
$.ajax({
method: "POST",
url: "upload.php",
data: {data: output, fileName: 'order-123.pdf'},
}).done(function(data) {
console.log('all done');
//view errors
console.log(data);
});
//Then, let the client print the document.
window.print();
});
}
这基本上是对发票进行截图,创建一个base64字符串,并将base64字符串放入pdf中并上传到服务器。
在此示例中,upload.php 是实际将 pdf 保存在服务器上的页面,如下所示:
if(isset($_POST['data'])){
$data = base64_decode($_POST['data']);
if (isset($_POST['fileName'])) {
$file = $_POST['fileName'];
} else {
$file = "order-" . rand(10,1000) . ".pdf";
}
file_put_contents($file, $data);
echo "Succes";
} else {
echo "No Data Sent";
}
exit();
它将创建以下 pdf:
Chrome and firefox
<img src="https://i.stack.imgur.com/m4gBc.png" width="600px" />
Safari
<img src="https://i.stack.imgur.com/w2x8K.png" width="600px" />
如您所见,它在 chrome 和 firefox 上比在 safari 上效果更好,因为 fontawesome 和 html2canvas 在 safari 上不能很好地协同工作(不知道为什么)。
我希望我能澄清一些事情。如有任何问题,请发表评论!
编辑
因为我在服务器端找不到任何其他支持“flex”的“Dom to pdf”,所以我创建了一个适用于客户端的示例。