MPDF-feof(),ftell(),fseek()和fread()错误-目录

时间:2019-04-03 15:05:13

标签: php mpdf

我正在使用以下库来生成pdf文件-> https://mpdf.github.io/

MPDF版本-> 7.1.7(升级到8.0.0)

我生成了很多PDF,然后编写了一个脚本将它们全部组合成一个已编译的PDF。一切顺利,PDF长达655页。

每当我尝试将TOC添加到pdf时,问题就来了。程序遇到一个无限错误,说feof(),ftell(),fseek()和fread()出现错误“提供的资源不是有效的流资源”。仅当我尝试添加目录时才会发生这种情况。

enter image description here

以下是合并代码。它会扫描特定目录,确定它是文件还是子目录,然后获取pdf并将其导入。

    function import_page($pdf, $path) {
        $page_count = $pdf -> SetSourceFile($path);
        for($j = 1; $j <= $page_count; $j++) {
            $page_id = $pdf -> ImportPage($j);
            $pdf -> UseTemplate($page_id);
            if($j < $page_count) {
                $pdf -> AddPage();
            }
        }
    }
    $pdf = new \Mpdf\Mpdf([
        'mode' => 'utf-8',
        'format' => 'Letter-P'
    ]);
    $pdf -> SetImportUse();

    $pdf -> WriteHTML('<tocpagebreak links="1" toc-preHTML="&lt;h2&gt;Table of Contents&lt;/h2&gt;" toc-resetpagenum="1" />');

    $files = scandir('../../output/');
    natsort($files);

    foreach($files as $file) {
        if(strpos($file, ".pdf") !== false) { // File
            $title = substr($file, strpos($file, '.') + 2, -4);
            $pdf -> TOC_Entry(htmlspecialchars($title, ENT_QUOTES), 0);

            import_page($pdf, '../../output/' . $file);
            $pdf -> WriteHTML('<pagebreak>');
        } elseif($file !== "." && $file !== "..") { // Directory
            $title = substr($file, strpos($file, '.') + 2);
            $pdf -> TOC_Entry(htmlspecialchars($title, ENT_QUOTES), 0);

            $sub_files = scandir('../../output/' . $file . '/');
            natsort($sub_files);

            foreach($sub_files as $sub_file) {
                if(strpos($sub_file, ".pdf") !== false) { // File
                    $sub_title = substr($sub_file, strpos($sub_file, '.') + 2, -4);
                    $pdf -> TOC_Entry(htmlspecialchars($sub_title, ENT_QUOTES), 1);

                    import_page($pdf, '../../output/' . $file . '/' . $sub_file);
                    $pdf -> WriteHTML('<pagebreak>');
                }
            }
        }
    }

    $pdf -> Output();

只要将tocpagebreak行注释掉,此代码就可以完美运行。一旦我尝试添加它,所有的地狱就会崩溃。

希望...我很傻,错过了一些简单的事情。在此先感谢所有回复,

修复尝试

-将writehtml TOC移至文档末尾,或在其之前添加页面。结果:失败。

-从tocpagebreak中删除所有设置,尝试使用方法tocpagebreak和tocpagebreakarray。结果:失败。

-注释掉if块的一个部分或另一部分(单个文件或子目录)。结果:通过。

-在单个子目录迭代之后中断循环。结果:通过。

-保存已编译的pdf。只需编写该页面的快速导入,然后尝试添加目录。结果:失败。

-将MPDF版本升级到8.0.0。结果:失败。

1 个答案:

答案 0 :(得分:0)

默认情况下,将PDF源文件设置为文件名字符串时,将创建启用closeStream标志的StreamReader对象。

    $page_count = $pdf -> SetSourceFile($path);

这里的问题是在TOC生成过程中进行深层对象克隆,MPDF对象以及所有StreamReader对象都将被克隆。

当克隆的TOC对象超出范围时,将收集其垃圾,并调用克隆的StreamReader类的析构函数,并关闭文件句柄,从而在原始对象中导致无效流。

解决方案是将PDF源文件设置为StreamReader对象,并禁用closeStream标志。

使用您的示例,它看起来应该像这样:

    function import_page($pdf, $path) {
        $fh = fopen($path, 'rb');
        $sr = new StreamReader($fh, false);
        $page_count = $pdf -> SetSourceFile(sr);
        for($j = 1; $j <= $page_count; $j++) {
            $page_id = $pdf -> ImportPage($j);
            $pdf -> UseTemplate($page_id);
            if($j < $page_count) {
                $pdf -> AddPage();
            }
        }
    }