Reputation: 191
Please read carefully,I have a job,the job is convert a html to pdf,and let the user download it.I know there is many choices to do this.But finally I chose wkhtmltopdf.In order to use it, I need to use php execute Linux command.Here is what I doing:
First,i use a redis queue to receive the convert job.When the user click the download button,I add a job to the queue.There is another script which read from the queue and process the convert job.
In the request file, I wrote some code to make sure when the convert action is complete we will send the file to browser.
if (file_exists($newFile)) {
return $this->output($fileName, $output, $newFile);
}
self::addJob([
'file' => $tmpFile,
'type' => Ap_Service_Data_ProcessPdf::html_to_pdf
]);
$try_times = 0;
//waiting for convert, try 10 times
while (true) {
if ($try_times >= 10) {
break;
}
clearstatcache();
if (is_file($newFile)) {
sleep(1);
return $this->output($fileName, $output, $newFile);
break;
}
$try_times++;
sleep(1);
}
-----------------------------------------------------------------
// the output function is something like this:
if (!file_exists($filePath)) {
header('HTTP/1.1 404 NOT FOUND');
} else {
$file = fopen($filePath, "rb");
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");
Header("Accept-Length: " . filesize($filePath));
Header("Content-Disposition: attachment; filename=" . $fileName);
echo fread($file, filesize($filePath));
fclose($file);
exit ();
}
Most times, this works good.The biggest problem is sometimes the browser never get the file and failed(10s timeout).It seems that the file is alreay there but the php script don't detect it,so it will try 10 times and wait for 10s,then return false.
I hope someone understand what I say, if there is something better solution, please tell me!
Upvotes: 1
Views: 794
Reputation: 1372
You can use this project as a PHP wrapper for wkhtmltopdf. For doing the same type of Job, I made a separate project available here. For using toPDF, you have to get the HTML code of your page and send it with the POST request for toPDF.
Here's is a glimpse how you can get the HTML (First, bound your html code with <pdf>
tag):
var x = document.querySelectorAll("pdf")[0].innerHTML;
var y = x.replace(/\n\s+|\n/g, "");
var styleSheetList = document.styleSheets;
var link = '';
for (var i = 0; i < styleSheetList.length; i++) {
if (styleSheetList[i].href != null) {
link += '<link rel="stylesheet" href="' + styleSheetList[i].href + '"/>';
}
}
var html = '<html><head><title>' + type + '</title><base href="">' + link + '</head><body>' + y + '</body></html>';
var data = {
html: html,
number: sr,
type: type,
};
//this path must be change to the host path
var path = 'api/generatePdf'; //path to your curl request to toPDF.
post(path, data, 'POST');
function post(path, params, method) {
method = method || "post"; // Set method to post by default if not specified.
// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for (var key in params) {
if (params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
Upvotes: 1