如何为Xerox打印机创建动态作业单?

时间:2011-05-18 21:58:58

标签: python pdf printing reportlab jdf

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

我的问题是我需要指示打印机应打印每页的介质类型(例如,文档第一页的预打印信头)。我似乎需要生成某种持有此类信息的工作单。

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

理想情况下,我需要一个可与我们的Freeflow服务器版本7和Xerox DocuSP打印机配合使用的解决方案。我尝试将JDF票证发送到这些打印机失败了。

我可以使用其他类型的票务系统,还是让所有打印机识别JDF文件?

3 个答案:

答案 0 :(得分:6)

我遇到了同样的问题。最后,我发现由于对PDF格式的误解导致我采用了错误的方式。我们认为PDF文件是打印机的WYSIWYG。不是这种情况。在任何类型的打印流程中,PDF文件通常会转换为某种中间格式,PostScriptTIFF图像或PCL

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

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

您有两种解决方案:

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

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

  3. 这类似于将C程序转换为程序集以将其移植到新架构的想法。它主要起作用,但你必须把每个系统都搞砸了。

    假设的管道是:

      

    创建PDF文件>通过PDF-to-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;
    }
    

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

    使用flexGCC编译代码:

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

    它通过stdin接受输入并输出到stdout。

    下面列出了更完整的词法分析器。它使用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;
    }
    

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:1)

我在Xerox support forum上收到了“ RogerK-Xerox ”的回复。

  

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

     

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

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

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

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