PHP/Ajax PDF 生成超时
Posted
技术标签:
【中文标题】PHP/Ajax PDF 生成超时【英文标题】:PHP/Ajax PDF generation timeout 【发布时间】:2015-03-16 13:56:24 【问题描述】:我在 php/ajax/jquery 中有一个代码,可以使用数据库中的值创建文档。但是当用户想要生成大量的 pdf 和 word 文件时,我遇到了生成大量文件所需的时间问题。
对于数组中的每个元素,我想创建一个 pdf 或 word,其中包含来自 mysql 数据库的该行 ID 的数据。 文件生成效果很好,我使用了:http://phpword.codeplex.com/ 和 mPDF。
1 个文件的生成时间约为 2-3 秒。当用户想要生成 500 条记录并将其打包为 .zip 时,我遇到了问题。
我的代码如下所示:
在客户端我创建了数组并通过 ajax 调用发送它:
function()
var ids = new Array();
$.ajax(
type: 'POST',
url: 'ajax/generate_pdf.php',
data:
'filename': $("#filename").val(),
'idPDF': ids.toString()
)
.done(function (data)
$("#filename").val("");
$("#message").append("Loading.<br/>");
$("#message").append(data);
)
.fail(function ()
alert("Error..");
);
我的 generate_pdf.php 文件如下所示:
<?php
// pdf library
include_once 'pdf/mpdf.php';
// name of zip
$filename=htmlspecialchars($_POST['filename']);
// open a zip
$zip = new ZipArchive();
$zip->open('../documents/'.$filename.'.zip', ZipArchive::CREATE);
header('Content-type: text/plain; charset=utf-8');
// get id's of rows sent by ajax
if(isset($_POST['idPDF']))
$setid=$_POST['idPDF'];
$rows=explode(',',$setid);
$count=count($rows);
for($i=0;$i<$count;$i++)
// id of every row
$id=$rows[$i];
// query to read data for file creation
$upit = "SELECT * FROM table WHERE id=?";
// here i read everything from database using PDO functions
// then i create html that will be written to pdf
$html .=' test ';
// mpdf
$mpdf=new mPDF();
// define paper
$mpdf=new mPDF('utf-8', array(176,250));
// some css
$style = '<style>
@page
margin-left: 10mm;
margin-bottom: 0mm;
</style>
';
// writting to pdf
$mpdf->WriteHTML($style);
$mpdf->WriteHTML($html);
// defining a name of pdf
$filenameID = $somevaluefromdatabaseUNIQUE.'-'.$filename;
$filenameID=preg_replace('/\s+/', '', $filenameID);
$filenameID=str_replace('/', '-', $filenameID);
// creating pdf
$mpdf->Output('../documents/'.$filenameID.'.pdf','F');
// add pdf to zip
$zip->addFile('../documents/'.$$filenameID.'.pdf', ''.$filenameID.'.pdf');
// close the zip
$zip->close();
// returned message via ajax
echo '<a href="documents/'.$filename.'.zip">Download generated pdf's.</a><br/>';
?>
【问题讨论】:
您可能必须将最初的文件请求与文件的实际送达分开。一种方法是使用作业队列。初始请求将向队列中添加一个条目并返回一个 ID 或令牌。在后台,cron 每隔几分钟就会运行一次,并检查作业队列中的新项目。当它找到一个时,它会生成该作业的所有文档并标记该作业已准备就绪。在客户端,在您的初始请求之后,您会定期查询作业状态,完成后通知用户他们的文档已准备好(光滑:电子邮件)。 Paypal 使用这种方法。 【参考方案1】:您遇到请求超时的问题。你可以:
通过将 0 传递给以下函数,告诉您的 php 没有运行脚本的最长时间:
set_time_limit(0);
http://php.net/manual/en/function.set-time-limit.php
重构您的代码,以便客户端每隔几秒发送 1 个 ajax 请求,而服务器始终为每个请求生成 1 个 PDF。
以上两个选项都会让客户端等待很长时间。你对此无能为力,事情需要时间。您可以做的是改善用户体验,就像 Google Drive 在您尝试上传非常大的文件时所做的那样,它会在完成该过程时通知您(例如通过电子邮件)。您可以将您的呼叫队列中要生成的 PDF 文档的 ID,例如在数据库中,然后一个 cron 作业在队列中运行并实际生成它,这样用户就可以从“加载”屏幕中解放出来。当您的(异步)流程结束时,通过电子邮件(如果有)或适合您的用户案例的任何其他选项通知客户。
【讨论】:
是的,我知道 set_time_limit 并且我使用它。使用 cron 作业是个好主意,但由于客户需求,我不能使用它。感谢您的想法;)以上是关于PHP/Ajax PDF 生成超时的主要内容,如果未能解决你的问题,请参考以下文章