使用ghostscript压缩PDF时省略临时文件

时间:2015-04-23 16:54:12

标签: perl ghostscript mojolicious

为了压缩上传的PDF文件,然后将它们存储到数据库中,我将这段代码放在一个mojolicious控制器中:

    # if > 100k compress with gs
    my $pdf;
    if ($size > 100_000) {
        # create tmp-file to be read by gs
        my $tmp_fn = '/tmp/badb_pdf_input.pdf';
        $file->move_to("$tmp_fn");

        use Capture::Tiny 'capture';
        my ($stdout, $stderr, $exit) = capture {
            my $cmd = '/usr/local/bin/gs';
            my @args = (qw( -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=- )) ;
            push @args, $tmp_fn;
            system($cmd, @args) == 0
                 or die "system @args failed: $!"
        };
        die "ERROR compressing pdf: $stderr" if $stderr;
        unlink $tmp_fn;
        $pdf = $stdout;
    } else {
        $pdf = $file->slurp;
    }

有没有人知道一种方法,以避免输入临时文件(/tmp/badb_pdf_input.pdf)?

2 个答案:

答案 0 :(得分:1)

首先,您不能压缩PDF文件'。您正在做的是解释原始PDF文件,创建一系列标记操作,然后从这些标记操作创建新的PDF文件。这不是一回事,重要的是要理解差异。

例如,可能的一件事就是对数据进行颜色转换,或降低图像的分辨率(两者都可能在您选择/电子书时发生)。如果你只是压缩'你不会改变数据的文件,所以这些变化都是不可能的。

但是,您也可能丢失信息。 Ghostscript的pdfwrite设备的唯一目标是视觉外观应该保持不变(如果你改变分辨率等,这是合理的)。可能无法保留元数据。实际上,pdfwrite设备不保留某些元数据(例如嵌入式Illustrator文件)这一事实是它可以生成较小PDF文件的部分原因。

我对“mojolicious”'但是你似乎试图通过stdin将数据发送到Ghostscript并从stdout读取生成的PDF?

如果是这样,那么您实际上将创建许多临时文件。通常,从标准输入处理PDF文件是不可能的,因为PDF格式需要随机访问文件。因此,如果您将PDF文件传输到stdin,Ghostscript将要做的第一件事就是创建一个临时文件,并将从stdin输入的PDF文件放入其中。然后它可以解释文件。此外,pdfwrite将在创建输出时创建大量临时文件。

你可以'选择stdout作为PDF文件的目的地,但是......

正如我所提到的,PDF格式是随机访问的,并且通常的做法是写入文件的一部分,为你还不知道的位留出空间,然后倒回文件并在你做的时填写它们。显然,这不会与不可寻找的流一起工作。目前,pdfwrite设备仅在创建线性化(针对快速Web视图优化)PDF文件时执行此操作,但我不能保证未来版本的pdfwrite不需要能够在输出文件中进行搜索。 / p>

所以简短的回答是你可以将OutputFile设置为stdout,但不能保证工作。

答案 1 :(得分:0)

如果上传的pdf的大小超过256 KB(默认情况下,请参阅max_memory_size),那么您不需要将其保存为临时文件,因为它已保存。

Here是如何获取文件路径的最小示例。

相关问题