6

我正在 Python 和Reportlab Toolkit中以编程方式创建 PDF 文件,每个文件都包含数千个文档,每个文档都有可变数量的页面。

我的问题是我需要指示打印机每页应该打印哪种介质类型(例如,文档第一页的预打印信头)。看来我需要生成某种包含此类信息的工作票。

我在创建 JDF 作业单方面取得了一些成功,但这些仅在我组织的运行 Xerox Freeflow Server 版本 8 的最新打印机上运行。

理想情况下,我需要一个也适用于我们的 Freeflow 服务器版本 7 和 Xerox DocuSP 打印机的解决方案。我曾尝试将 JDF 票证发送到这些打印机,但未成功。

我可以使用其他类型的票务系统,或者让我们所有的打印机识别 JDF 文件的方法吗?

4

3 回答 3

6

我遇到了同样的问题。最终,由于对PDF格式的误解,我发现我走错了路。我们将 PDF 文件视为打印机的所见即所得。不是这种情况。在任何类型的打印流程中,PDF 文件通常都会转换为某种中间格式、PostScriptTIFF图像或PCL

这可能发生在您的本地机器上,这就是您需要驱动程序的原因,也可能发生在打印机本身上。如果它发生在打印机上,您只是将 PDF 文件传输到设置了适当转换系统的另一台计算机上。

这一切都很好而且很花哨,除了PDF 没有定义页面顺序,这对于打印就绪格式来说是非常违反直觉的。这意味着您的文档没有第一页,您将无法以任何方式在本地定义它的形状或形式。

你有两个解决方案:

  1. 选择一种打印机架构并使用其独特的设置介质类型的方法,这是一种痛苦且不可移植的方法。

  2. 转换为允许设置媒体类型并包含页面排序概念的格式,例如 PostScript。然后添加您的媒体命令并将此文件发送到您的打印机。如果您的打印机有用于读取您选择的中间格式的驱动程序,它应该将命令转换为它的媒体切换版本。这更便携,但仍然不完美。

这类似于将C程序转换为汇编以将其移植到新架构的想法。它主要是有效的,但你必须让每个系统都运行起来。

一个假设的管道将是:

创建您的 PDF 文件 > 通过 PDF 到 PostScript 转换实用程序或库运行它 > 通过自定义词法分析器运行以在每个新页面上添加媒体类型命令 > 将 PostScript 文件发送到打印机

这是很多工作,但这是您唯一能找到解决问题的方法。

样本

%{
char paper[] = 'yourPaper';
%}
%option 8bit outfile="scanner.c"
%option nounput nomain noyywrap
%option warn

%%
showpage { printf("showpage\nsetpagedevice MediaType '%s'", paper); }
%%
int main(int argc, char **argv);

int main (argc,argv)
int argc;
char **argv;
{
    yylex();
    return 0;
}

上面是一个非常简单的词法分析器,用于查找从 stdin 获得的每个 showpage 命令并输出一个 showpage setpagedevice 命令集。setpagedevice MediaType 命令是设置用于页面的纸张类型的与打印机无关的方式。

使用flexGCC编译代码:

flex -Cf scanner.l
gcc -O -o lineCount.exe scanner.c

它通过标准输入接受输入并输出到标准输出。

下面列出了一个更完整的词法分析器。它使用 GNU getopts作为命令行选项,并且有两个规则,因此它也会为第一页设置页面设​​备。它可能无法完美抓取页面,并且它只有一个用于纸张类型的变量,因此功能有限。另一方面,它非常开放,但您希望它确定要使用的页面设备。

识别正在查看的页面类型的新规则,或者每页一行一行的附加输入文件是立即想到的两个。

/*
 * This file is part of flex.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * Neither the name of the University nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

     /**************************************************
        Start of definitions section

    ***************************************************/

%{
/* A template scanner file to build "scanner.c". */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
/*#include "parser.h" */

//put your variables here
char FileName[256];
FILE *outfile;
char inputName[256];
char paper[] = 'yourPaper';

// flags for command line options
static int specificFile_flag = 0;
static int output_flag = 0;
static int help_flag = 0;

%}


%option 8bit outfile="scanner.c"
%option nounput nomain noyywrap
%option warn

%%
    /************************************************
        start of rules section

    *************************************************/


    /* These flex patterns will eat all input */
EndSetup { printf("showpage\nsetpagedevice MediaType '%s'", paper); }
showpage { printf("showpage\nsetpagedevice MediaType '%s'", paper); }


%%
    /****************************************************
        Start of code section


    *****************************************************/

int main(int argc, char **argv);

int main (argc,argv)
int argc;
char **argv;
{
    /****************************************************
        The main method drives the program. It gets the filename from the
        command line, and opens the initial files to write to. Then it calls the lexer.
        After the lexer returns, the main method finishes out the report file,
        closes all of the open files, and prints out to the command line to let the
        user know it is finished.
    ****************************************************/

    int c;

    // The GNU getopt library is used to parse the command line for flags
    // afterwards, the final option is assumed to be the input file

    while (1) {
        static struct option long_options[] = {
            /* These options set a flag. */
            {"help",   no_argument,     &help_flag, 1},
            /* These options don't set a flag. We distinguish them by their indices. */

            {"useStdOut", no_argument,       0, 'o'},
            {0, 0, 0, 0}
        };
           /* getopt_long stores the option index here. */
        int option_index = 0;
        c = getopt_long (argc, argv, "o",
            long_options, &option_index);

        /* Detect the end of the options. */
        if (c == -1)
            break;

        switch (c) {
            case 0:
               /* If this option set a flag, do nothing else now. */
               if (long_options[option_index].flag != 0)
                 break;
               printf ("option %s", long_options[option_index].name);
               if (optarg)
                 printf (" with arg %s", optarg);
               printf ("\n");
               break;

            case 'o':
               output_flag = 1;
               break;


            case '?':
               /* getopt_long already printed an error message. */
               break;

            default:
               abort ();
            }
    }

    if (help_flag == 1) {
        printf("proper syntax is: traySwitch.exe [OPTIONS]... INFILE OUTFILE\n");
        printf("adds tray switching information to postscript file\n\n");
        printf("Option list: \n");
        printf("-o                        sets output to stdout\n");
        printf("--help                   print help to screen\n");
        printf("\n");
        printf("inputfile example: traySwitch.exe test.ps\n");
        printf("If infile is left out, then stdin is used for input.\n");
        printf("If outfile is a filename, then that file is used.\n");
        printf("If there is no outfile, then infile-EDIT.ps is used.\n");
        printf("There cannot be an outfile without an infile.\n");
        return 0;
    }

    //Get the filename off the command line and redirect it to input
    //if there is no filename or it is a - then use stdin.


    if (optind < argc) {
        FILE *file;

        file = fopen(argv[optind], "rb");
        if (!file) {
            fprintf(stderr, "Flex could not open %s\n",argv[optind]);
            exit(1);
        }
        yyin = file;
        strcpy(inputName, argv[optind]);
    }
    else {
        printf("no input file set, using stdin. Press ctrl-c to quit");
        yyin = stdin;
        strcpy(inputName, "\b\b\b\b\bagainst stdin");
    }

    //Increment current place in argument list
    optind++;


    /********************************************
        If no input name, then output set to stdout.
        If no output name then copy input name and add -EDIT.csv.
        If input name is '-' then output set to stdout,
        otherwise use output name.

    *********************************************/
    if (optind > argc) {
        yyout = stdout;
    }
    else if (output_flag == 1) {
        yyout = stdout;
    }
    else if (optind < argc){
        outfile = fopen(argv[optind], "wb");
        if (!outfile) {
            fprintf(stderr, "Flex could not open %s\n",FileName);
            exit(1);
        }
        yyout = outfile;
    }
    else {
        strncpy(FileName, argv[optind-1], strlen(argv[optind-1])-4);
        FileName[strlen(argv[optind-1])-4] = '\0';
        strcat(FileName, "-EDIT.ps");
        outfile = fopen(FileName, "wb");
        if (!outfile) {
            fprintf(stderr, "Flex could not open %s\n",FileName);
            exit(1);
        }
        yyout = outfile;
    }

    yylex();
    if (output_flag == 0) {
        fclose(yyout);
    }
    printf("Flex program finished running file %s\n", inputName);
    return 0;
}
于 2011-05-23T15:03:09.583 回答
2

您应该向您的打印机供应商 (Xerox) 询问有关其 DocuSp 打印机的 JDF 支持范围的规范。

您可能很幸运并获得了信息。

除了 JDF,没有其他标准化的工作票证方式。还有其他几种特定于供应商的方法,施乐很可能有自己的方法。问他们。

于 2011-05-21T11:13:49.693 回答
1

我在Xerox 支持论坛上收到了来自“ RogerK-Xerox ”的回复。

Xerox 使用基于 XML 的票务系统,称为 Xerox 打印指令格式 (XPIF)。您可以通过打开 Xerox 自定义打印驱动程序、编程一些打印属性,然后导出 Xerox Job Ticket 来了解这种格式的工作原理。这是通过选择打印驱动程序上的“高级”选项卡,选择 Xerox 作业单旁边的“+”并选择“导出 Xerox 作业单...”,然后按“导出...”按钮来完成的。

为了完全访问 XPIF 编程指南,我相信您必须在http://www.xerox-solutions.net/Partners上注册

我尝试了上述方法,它确实生成了一个带有作业单说明的 XML 文件,大概可以在打印驱动程序中重新加载。现在我正在寻找一种将这些文件与打印机热文件夹一起使用的方法,这更符合我们当前的工作流程。打印机需要以某种方式知道哪个 XPIF 票据属于哪个 PDF 文件。

似乎可以通过简单地连接两个文件来将 XPIF 文件添加到 PDF 文件的开头。然后可以将文件拖入热文件夹,施乐打印机知道如何将作业单与 PDF 分开。

我已经测试了这种方法,它按预期工作:-)。将一些任意 XML 数据附加到 PDF 文件的开头会使其无法在 Adob​​e Acrobat 中打开。但令人惊讶的是,这些文件在 Evince Document Viewer 中打开得很好。

于 2011-05-23T23:21:04.737 回答