将大量 pdf 导入 mPDF 导致 /fopen 失败
Importing large number of pdfs into mPDF is causing /fopen to fail
编辑:在 Jan
的协助下更新
编辑:代码直到 $mpdf->Output($max . ' imports .pdf', 'D') 才会失败;被称为
PHP 版本 7.1
MPDF 版本 8.0.10
Setasign fpdi_pdf-parser 版本 2.0.4
错误
Failed to open file (fopen) Compnay Induction (checklist) th v2.pdf
Failed to open file (fopen) Information Register for Employees.pdf
Failed to open file (fopen) Coshh listings v7.pdf Failed to open file
(fopen) Emp Competency Form.pdf
下面是我产生错误的代码片段
function addCustomForms($forms, $mpdf, $Customer)
{
if ($forms) {
$handles = [];
foreach ($forms as $CustomPolicyForm) {
if (is_file('../cdata/' . $Customer->reference . '/policy-forms/' . $CustomPolicyForm->form)) {
try {
$h = \fopen('../cdata/' . $Customer->reference . '/policy-forms/' . $CustomPolicyForm->form, 'rb');
// File not Opened
if ($h === false) {
echo 'Failed to open file (fopen) ' . $CustomPolicyForm->form . '<br/>';
return false;
} else {
$stream = new \setasign\Fpdi\PdfParser\StreamReader($h, false);
$pagecount = $mpdf->setSourceFile($stream);
if ($pagecount > 0) {
for ($i = 1; $i <= ($pagecount); $i++) {
$mpdf->AddPage($CustomPolicyForm->orientation);
if ($i == 1) {
$html = '<h3 style="color: #ffffff;">' . sd($CustomPolicyForm->title) . '</h3>';
$mpdf->WriteHTML($html);
}
try {
$import_page = $mpdf->importPage($i);
try {
$mpdf->useTemplate($import_page);
} catch (Exception $e) {
echo 'Not worked for ' . $CustomPolicyForm->title .'<br/>';
return false;
}
} catch (Exception $e) {
echo 'importPage failed for ' . $CustomPolicyForm->title . ' Page ' . $i .'<br/>';
return false;
}
}
$handles[] = $h;
} else {
echo 'Page count is less than 1 for ' . $CustomPolicyForm->form .'<br/>';
return false;
}
}
} catch
(Exception $e) {
echo 'Failed to set source file for ' . $CustomPolicyForm->form . '<br/>';
return false;
}
} else {
echo 'File not found: ' . $CustomPolicyForm->form .'<br/>';
return false;
}
$pagecount = null;
}
return $handles;
} else {
// No forms found
echo 'No Forms Found';
return false;
}
}
$mpdf->Output(Customer::find_by_id($Policy->customer_id)->customer . '.pdf', 'D');
\fclose($handles);
Changing TOCuseLinking' => false hides/resolves 问题,但我不确定首先导致问题的原因。
我使用的测试文件是https://1drv.ms/b/s!ApXTTaxD_QQPj7kwpxX3G4a5-2Ir2Q?e=WJRMi3(这是一个空白PDF)
有人指点一下吗?
mPDF 的 TOC 功能试图通过克隆整个实例并重置它来施展魔法……我没有深入研究它。但是通过这种方式,对流阅读器的引用是未设置的。由于对象数量的原因,稍后会触发垃圾收集器,这会触发 __destruct()
方法,然后关闭流句柄。
要绕过这个问题,您需要控制文件句柄。您的示例可以这样重写:
$h = \fopen('BLANK PDF.pdf', 'rb');
$stream = new \setasign\Fpdi\PdfParser\StreamReader($h, false);
for ($count = 0; $count < $max; $count++) {
$pagecount = $mpdf->setSourceFile($stream);
if ($pagecount > 0) {
$mpdf->AddPage();
for ($i = 1; $i <= ($pagecount); $i++) {
if ($i == 1) {
$html = '<h3 style="color: #000;">' . htmlentities('Blank PDF ' . $count) . '</h3>';
$mpdf->WriteHTML($html);
}
$import_page = $mpdf->importPage($i);
$mpdf->useTemplate($import_page);
}
} else {
return false;
}
}
$mpdf->Output($max . ' imports .pdf', 'F');
fclose($h);
如果您需要处理不同的文件,请将句柄存储在一个数组中以保留它们的引用。
您还应该注意到操作系统对打开的文件句柄有限制。 FPDI 受此限制。
编辑:在 Jan
的协助下更新编辑:代码直到 $mpdf->Output($max . ' imports .pdf', 'D') 才会失败;被称为
PHP 版本 7.1
MPDF 版本 8.0.10
Setasign fpdi_pdf-parser 版本 2.0.4 错误
Failed to open file (fopen) Compnay Induction (checklist) th v2.pdf Failed to open file (fopen) Information Register for Employees.pdf Failed to open file (fopen) Coshh listings v7.pdf Failed to open file (fopen) Emp Competency Form.pdf
下面是我产生错误的代码片段
function addCustomForms($forms, $mpdf, $Customer)
{
if ($forms) {
$handles = [];
foreach ($forms as $CustomPolicyForm) {
if (is_file('../cdata/' . $Customer->reference . '/policy-forms/' . $CustomPolicyForm->form)) {
try {
$h = \fopen('../cdata/' . $Customer->reference . '/policy-forms/' . $CustomPolicyForm->form, 'rb');
// File not Opened
if ($h === false) {
echo 'Failed to open file (fopen) ' . $CustomPolicyForm->form . '<br/>';
return false;
} else {
$stream = new \setasign\Fpdi\PdfParser\StreamReader($h, false);
$pagecount = $mpdf->setSourceFile($stream);
if ($pagecount > 0) {
for ($i = 1; $i <= ($pagecount); $i++) {
$mpdf->AddPage($CustomPolicyForm->orientation);
if ($i == 1) {
$html = '<h3 style="color: #ffffff;">' . sd($CustomPolicyForm->title) . '</h3>';
$mpdf->WriteHTML($html);
}
try {
$import_page = $mpdf->importPage($i);
try {
$mpdf->useTemplate($import_page);
} catch (Exception $e) {
echo 'Not worked for ' . $CustomPolicyForm->title .'<br/>';
return false;
}
} catch (Exception $e) {
echo 'importPage failed for ' . $CustomPolicyForm->title . ' Page ' . $i .'<br/>';
return false;
}
}
$handles[] = $h;
} else {
echo 'Page count is less than 1 for ' . $CustomPolicyForm->form .'<br/>';
return false;
}
}
} catch
(Exception $e) {
echo 'Failed to set source file for ' . $CustomPolicyForm->form . '<br/>';
return false;
}
} else {
echo 'File not found: ' . $CustomPolicyForm->form .'<br/>';
return false;
}
$pagecount = null;
}
return $handles;
} else {
// No forms found
echo 'No Forms Found';
return false;
}
}
$mpdf->Output(Customer::find_by_id($Policy->customer_id)->customer . '.pdf', 'D');
\fclose($handles);
Changing TOCuseLinking' => false hides/resolves 问题,但我不确定首先导致问题的原因。
我使用的测试文件是https://1drv.ms/b/s!ApXTTaxD_QQPj7kwpxX3G4a5-2Ir2Q?e=WJRMi3(这是一个空白PDF)
有人指点一下吗?
mPDF 的 TOC 功能试图通过克隆整个实例并重置它来施展魔法……我没有深入研究它。但是通过这种方式,对流阅读器的引用是未设置的。由于对象数量的原因,稍后会触发垃圾收集器,这会触发 __destruct()
方法,然后关闭流句柄。
要绕过这个问题,您需要控制文件句柄。您的示例可以这样重写:
$h = \fopen('BLANK PDF.pdf', 'rb');
$stream = new \setasign\Fpdi\PdfParser\StreamReader($h, false);
for ($count = 0; $count < $max; $count++) {
$pagecount = $mpdf->setSourceFile($stream);
if ($pagecount > 0) {
$mpdf->AddPage();
for ($i = 1; $i <= ($pagecount); $i++) {
if ($i == 1) {
$html = '<h3 style="color: #000;">' . htmlentities('Blank PDF ' . $count) . '</h3>';
$mpdf->WriteHTML($html);
}
$import_page = $mpdf->importPage($i);
$mpdf->useTemplate($import_page);
}
} else {
return false;
}
}
$mpdf->Output($max . ' imports .pdf', 'F');
fclose($h);
如果您需要处理不同的文件,请将句柄存储在一个数组中以保留它们的引用。
您还应该注意到操作系统对打开的文件句柄有限制。 FPDI 受此限制。