1

我正在尝试使用 Unoconv 将 .docx 文件转换为 .pdf 文件。Libreoffice 安装在我的服务器上,该脚本适用于服务器上的另一个网站。

使用该行use Unoconv\Unoconv;会产生HTTP ERROR 500.

有人知道我为什么得到一个HTTP ERROR 500吗?

这是我的脚本:

<?php
    require './Unoconv.php';
    use Unoconv\Unoconv;
        
    $originFilePath = './uf/invoice/17/word/202100021.docx';
    $outputDirPath  = './uf/invoice/17/pdf/202100021.pdf';
    
    Unoconv::convertToPdf($originFilePath, $outputDirPath);

    header("Content-type:application/pdf");
    header("Content-Disposition:attachment;filename=202100021.pdf");
?>

这是我的 Unoconv.php 脚本:

<?php

namespace Unoconv;

class Unoconv {

    public static function convert($originFilePath, $outputDirPath, $toFormat)
    {
        $command = 'unoconv --format %s --output %s %s';
        $command = sprintf($command, $toFormat, $outputDirPath, $originFilePath);
        system($command, $output);

        return $output;
    }

    public static function convertToPdf($originFilePath, $outputDirPath)
    {
        return self::convert($originFilePath, $outputDirPath, 'pdf');
    }

    public static function convertToTxt($originFilePath, $outputDirPath)
    {
        return self::convert($originFilePath, $outputDirPath, 'txt');
    }

}
?>
4

3 回答 3

2

从包装代码开始,try...catch首先获取错误消息:

<?php
try {
    require 'Unoconv.php';
    use Unoconv\Unoconv;
    
    $map1 = $_SESSION['companyid'];
    $filename = $result1['filename'];
    
    $originFilePath = './uf/doc/'.$map1.'/word/'.$filename.'.docx';
    $outputDirPath  = './uf/doc/'.$map1.'/pdf/'.$filename.'.pdf';
    
    Unoconv::convertToPdf($originFilePath, $outputDirPath);
    
    header("Content-type:application/pdf");
    header("Content-Disposition:attachment;filename=".$filename.".pdf");
    readfile($outputDirPath);
} catch (\Exception $e) {
    die($e->getMessage());
}
于 2021-09-13T14:53:37.683 回答
2

@Alex 关于首先包装 try/catch 是正确的,但语法应该是:

...
} catch(\Exception $e){
...
于 2021-09-14T04:22:44.520 回答
1

我观察到 LibreOffice 在进行转换时可能有点古怪,尤其是在从网络服务器帐户以无头模式运行时。

最简单的尝试是修改unoconv为使用与 LibreOffice 一起提供的相同 Python 二进制文件:

#!/usr/bin/env python

应该是(在检查 libreoffice 的安装位置之后)

#!/opt/libreoffice7.1/program/python

否则,我通过直接调用 libreoffice 解决了这个问题(没有 Unoconv):

    $dir    = dirname($docfile);
    // Libreoffice saves here
    $pdf    = $dir . DIRECTORY_SEPARATOR . basename($docfile, '.docx').'.pdf';
    $ret = shell_exec("export HOME={$dir} && /usr/bin/libreoffice --headless --convert-to pdf --outdir '{$dir}' '{$docfile}' 2>&1");
    if (file_exists($pdf)) {
        rename($pdf, $realPDFName);
    } else {
        return false;
    }
    return true;

所以你的代码会变成:

$originFilePath = './uf/invoice/17/word/202100021.docx';
$outputDirPath  = './uf/invoice/17/pdf/202100021.pdf';

$dir    = dirname($originFilePath);
$pdf    = $dir . DIRECTORY_SEPARATOR . basename($originFilePath, '.docx').'.pdf';
$ret = shell_exec("export HOME={$dir} && /usr/bin/libreoffice --headless --convert-to pdf --outdir '{$dir}' '{$originFilePath}' 2>&1");
// $ret will contain any errors
if (!file_exists($pdf)) {
    die("Conversion error: " . htmlentities($ret));
}
rename($pdf, $outputDirPath);

header("Content-type:application/pdf");
header("Content-Disposition:attachment;filename=202100021.pdf");
readfile($outputDirPath);

我假设 libreoffice 存在于“/usr/bin/libreoffice”的常用替代链接中,否则您需要使用“which libreoffice”的终端命令检索其路径。或者,从 php 脚本,

<?php
header('Content-Type: text/plain');
print "If this works:\n";
system('which libreoffice 2>&1');
print "\n-- otherwise a different attempt, returning too much information --\n";
system('locate libreoffice');
于 2021-09-19T18:46:26.197 回答