如何解决wkhtmltopdf无需在php中创建文件
我的 Drupal 中有 wkhtmltopdf 模块,它通过使用 'wkhtmltopdf --options URL filename.pdf'
函数运行 shell_exec
命令来生成 pdf 文件。
文件的输出很好,但我不想将pdf存储在文件系统中。我只想在浏览器上显示输出,以便用户可以选择是否下载。
就我搜索而言,我找不到一种方法可以将输出保存在缓冲区中,而不是将其存储在 pdf 文件中。 wkhtmltopdf不创建文件就可以生成pdf吗?
解决方法
GIF Demonstration (Over-engineered)
这是我为你写的一段过度设计的代码:)
它包括从功能到您可以测试的演示表单的所有内容。
我不保证此代码的稳定性,您可以随意查看 并对其进行修改以供您自己使用,但我不能保证 100% 的稳定性或安全性。
阅读有关 shell_exec 等函数的文档,以及为什么由于潜在的安全风险,这是一种不好的做法。
我的建议是用 C++ 编写一个 PHP 库并加载它并使用它 在 PHP 中。
我不确定 wkhtmltopdf 是否存在,如果我错了,有人在评论中纠正我。
更新 1
我在 http://ifconfig.me 上测试了这个脚本,它返回一个格式错误的 PDF 文档。
因此,您可能有 3 种选择,要么用 C++ 编写 PHP 库,等待有人提出更好的解决方案,要么将文件下载到 /tmp
中并使用 PHP 读取文件,然后将其删除。
代码(简单)
<?php
/**
* --- DO NOT REMOVE THIS DOCBLOCK ---
* @WebCrawlTrackingId cf9e8c67.3cb7269c.60b1d84b.5b2e5450
*/
/**
* @file
* Code for ni_wkhtmltopdf_simple function.
* Includes a demonstration at the end.
*/
/**
* Function that saves a PDF file
* to a temporary directory and
* returns it.
* All of this by using wkhtmltopdf.
*
* @author t3ap0t@stackoverflow.com
*
* @param string $url
* URL to convert
*
* @param string $download
* Decide whether to download the
* file by specifying a filename
* or don't specify anything to
* display it in the browsers
* built-in PDF viewer.
*
* @return int|file
* Return (int) -1 if URL is empty
* Return (int) -2 if URL is not a string
* Return (int) -3 if URL is not a URL
*/
function ni_wkhtmltopdf_simple($url = "",$download = false) {
// URL can't be empty
if ($url == "") {
return -1;
}
// URL must be a string
if (gettype($url) !== "string") {
return -2;
}
// Remove whitespace
$url = trim($url);
// Explode URL by ':' to Array
$urla = explode(":",$url,2);
// URL must be an actual URL
if (strtolower(substr($urla[0],4)) !== "http" || substr($urla[1],2) !== "//") {
return -3;
}
// Escape Shell Arguments
$url = escapeshellarg($url);
// Random file name
$fname = "/tmp/" . bin2hex(random_bytes(10)) . ".pdf";
// Generate a PDF file
shell_exec("wkhtmltopdf \"$url\" \"$fname\"");
// Load file
$buffer = file_get_contents("$fname");
// Delete the file after loading
unlink("$fname");
$buffsz = strlen($buffer);
// Prepare headers
header("Content-Type:application/pdf");
if ($download) {
$download = trim($download);
header("Content-Disposition:attachment;filename=\"$download\"");
} else {
header("Content-Disposition:inline");
}
header("Content-Length:" . $buffsz);
exit($buffer);
}
// Demonstrate ni_wkhtmltopdf_simple
// Are we getting the URL parameter?
if (isset($_GET["url"])) {
// Convert array to string
if (is_array($_GET["url"])) {
$_GET["url"] = $_GET["url"][0];
}
// Remove whitespace
$url = trim($_GET["url"]);
// URL is empty so unset it
if ($url == "") {
unset($_GET["url"],$url);
header("Location:" . basename(__FILE__));
}
// Get PDF output
if (isset($url)) {
ni_wkhtmltopdf_simple($url);
}
} else {
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>PHP wkhtmltopdf_simple Demo (t3ap0t@stackoverflow.com)</title>
<style>
*{outline:0}
html,body{
zoom:1.25
}
</style>
</head>
<body>
<form action="<?= basename(__FILE__) ?>" method="GET">
<label for="url">URL:</label>
<input id="url" name="url" type="text" value="https://" minlength="8" required autofocus />
<button id="btn" type="submit">Generate PDF</button>
<script type="text/javascript">
function urlhandler(e) {
// URL Value must begin with https://
if (url.value.trim() == "") {
url.value = "https://" + url.value;
}
// Prevent removal of https://
if (e.keyCode == 8 && url.value == "https://") {
e.preventDefault();
}
// Prevent Delete key
if (e.keyCode == 46) {
e.preventDefault();
}
// Add https:// if it was removed during Paste operation
if (url.value.substr(0,8).toLowerCase() !== "https://") {
url.value = "https://" + url.value;
}
}
function btnhandler(e) {
if (url.value.substr(0,8).toLowerCase() !== "https://") {
url.value = "https://" + url.value;
}
// Prevent submission of the form
e.preventDefault();
// Make sure we've provided a URL
if (8 >= url.value.trim().length ||
url.value.trim()[9] == ".") {
alert("You must provide a URL.");
return;
}
// Automatically guess top-level domain
if (url.value.trim().substr(-4,1) !== "." &&
url.value.trim().substr(-3,1) !== ".") {
url.value += ".com";
}
url.parentNode.submit();
}
// Event listeners
url.addEventListener("keydown",function(e) {
urlhandler(e);
});
url.addEventListener("onpaste",function(e) {
urlhandler(e);
});
btn.addEventListener("click",function(e) {
btnhandler(e);
});
</script>
</form>
</body>
<?php
}
?>
代码(过度设计)
<?php
/**
* --- DO NOT REMOVE THIS DOCBLOCK ---
* @WebCrawlTrackingId fcc5094e.ccc3a1df.5eb4dbfa.6c3772e1
*/
/**
* @file
* Code for ni_wkhtmltopdf function.
* Includes a demonstration at the end.
*/
/**
* Function that returns a PDF file
* from a URL using wkhtmltopdf.
*
* @author t3ap0t@stackoverflow.com
*
* @param string $url
* URL to convert
*
* @param string $https
* Ensures we're giving it HTTPS
*
* @param string $download
* Decide whether to download the
* file by specifying a filename
* or don't specify anything to
* display it in the browsers
* built-in PDF viewer.
*
* @param string $checkcmd
* Ensure we have all commands
* required to fulfil the operation.
*
* * On Windows hosts these commands
* can be acquired on using `scoop`.
*
* @param string $checkos
* Make sure we're running Linux.
*
* * Optional if we have both commands
* available on a Windows host.
*
*
* @return int|file
* Return (int) -1 if URL is empty
* Return (int) -2 if URL is not a string
* Return (int) -3 if URL is not a URL
* Return (int) -4 if protocol is not HTTPS
* Return (int) -5 if OS is not Linux
* Return (int) -6 if command wkhtmltopdf not found
* Return (int) -7 if command cat not found
* Return (int) -8 wkhtmltopdf returned nothing
*/
function ni_wkhtmltopdf($url = "",$https = false,$download = false,$checkcmd = true,$checkos = false) {
// URL can't be empty
if ($url == "") {
return -1;
}
// URL must be a string
if (gettype($url) !== "string") {
return -2;
}
// Remove whitespace
$url = trim($url);
// Explode URL by ':' to Array
$urla = explode(":",2) !== "//") {
return -3;
}
// Optional: Make sure the URL is HTTPS (Secure)
if ($https && strtolower(substr($url,8)) !== "https://") {
return -4;
}
// Optional: Check operating system
if ($checkos && strtolower(PHP_OS) !== "linux") {
return -5;
}
// Optional: (Linux) Make sure the `wkhtmltopdf` command exists
if ($checkcmd && !(`which wkhtmltopdf` > 0)) {
return -6;
}
// Optional: (Linux) Make sure the `cat` command exists
if ($checkcmd && !(`which cat` > 0)) {
return -7;
}
// Clear URL to (hopefully) prevent RCE
$rep = array(
" " => "%20","%20%20" => "","`" => "%60",";" => "%3B",":" => "%3A",">" => "%3E","<" => "%3C","[" => "%5B","]" => "%5D","{" => "%7B","}" => "%7D","(" => "%28",")" => "%29","|" => "%7C","$" => "%24","&&" => "%26%26",'"' => "%22","\\" => "%5C"
);
// Replace $a with $b inside URL
foreach ($rep as $a => $b) {
$url = str_replace($a,$b,$url);
}
unset($rep);
// Generate a PDF file
exec("wkhtmltopdf \"$url\" - | cat",$buffer);
$buffer = implode("\n",$buffer);
$buffsz = strlen($buffer);
// Is buffer empty?
if (0 >= $buffsz) {
return -8;
}
// Prepare headers
header("Content-Type:application/pdf");
if ($download) {
$download = trim($download);
header("Content-Disposition:attachment;filename=\"$download\"");
} else {
header("Content-Disposition:inline");
}
header("Content-Length:" . $buffsz);
exit($buffer);
}
// Demonstrate ni_wkhtmltopdf
// Are we getting the URL parameter?
if (isset($_GET["url"])) {
// Convert array to string
if (is_array($_GET["url"])) {
$_GET["url"] = $_GET["url"][0];
}
// Remove whitespace
$url = trim($_GET["url"]);
// URL is empty so unset it
if ($url == "") {
unset($_GET["url"],$url);
header("Location:" . basename(__FILE__));
}
// Get PDF output
if (isset($url)) {
ni_wkhtmltopdf($url);
}
} else {
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>PHP wkhtmltopdf Demo (t3ap0t@stackoverflow.com)</title>
<style>
*{outline:0}
html,function(e) {
btnhandler(e);
});
</script>
</form>
</body>
<?php
}
?>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。