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

发布于 2024-11-08 23:16:03 字数 459 浏览 5 评论 0原文

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

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

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

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

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

I am programmatically creating PDF files in Python and Reportlab Toolkit, each containing several thousand documents, each document with a variable amount of pages.

My problem is that I need to instruct the printer which media type each page should be printed on (pre-printed letterhead for the first page of a document for example). It seems that I need to generate some kind of job ticket which hold this kind of information.

I've had some success with creating JDF job tickets, but these only run on my organisation's newest printers which run Xerox Freeflow Server version 8.

Ideally, I need a solution which also works with our Freeflow server version 7 and Xerox DocuSP printers. I have tried unsuccessfully to send JDF tickets to these printers.

Is there another type of ticketing system I could use, or a way to get all of our printers recognising JDF files?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

骄傲 2024-11-15 23:16:03

我遇到了同样的问题。最终,我发现我的做法是错误的,这是由于对 PDF 格式。我们将 PDF 文件视为打印机的所见即所得。事实并非如此。在任何类型的打印流程中,PDF 文件都会转换为某种中间格式,PostScript, < a href="http://en.wikipedia.org/wiki/Tagged_Image_File_Format" rel="nofollow noreferrer">TIFF 图像,或 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;
}

I've run into the same problem. Eventually, I found out that I was going about it the wrong way, caused by a misunderstanding of the PDF format. We think of PDF files as WYSIWYG for printers. This is not the case. In any kind of print flow, the PDF file gets converted to some intermediate format, PostScript, TIFF images, or PCL usually.

This may happen on your local machine, which is why you need a driver, or on the printer itself. If it happens on the printer, you are just transferring your PDF file to a different computer with the appropriate conversion system set up.

This is all fine and dandy, except that PDF does not define page order which is very counterintuitive for a print ready format. This means there is no first page of your document and you won't be able to natively define it in any way shape or form.

You have two solutions:

  1. Pick a printer architecture and use its unique method of setting the media type, which is a pain, and nonportable.

  2. Convert to a format that allows for setting media type and includes the idea of page ordering, such as PostScript. Then add in your media commands and send this file along to your printer. If your printer has a driver for reading your chosen intermediate format, it should convert the commands to its version of media switching. This is more portable but still not perfect.

This is similar to the idea of converting your C program to assembly to port it to a new architecture. It mostly works, but you have to fiddle each system into operation.

A hypothetical pipeline would be:

Create your PDF file > run it through a PDF-to-PostScript conversion utility or library > run through a custom lexer to add media type commands at each new page > send to PostScript file to printer

It's a lot of work, but that's about the only thing your going to find that will solve your problem.

Sample

%{
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;
}

The above is a very simplistic lexer to find every showpage command obtained from stdin and output a showpage setpagedevice command set. The setpagedevice MediaType command is the printer agnostic way of setting the type of paper to use for a page.

To compile the code using flex and GCC:

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

It accepts input via stdin and outputs to stdout.

A more complete lexer is listed below. It uses GNU getopts for command line options, and has two rules, so that it will set the page device for the first page as well. It may not perfectly grab the pages, and it only has one variable for the paper type, so the functionality is limited. On the other hand, it is very open for however you want it to determine the page device to use.

Either new rules to recognize what type of page it is looking at, or an additional input file with one line per page are the two that come to mind immediately.

/*
 * 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;
}
苯莒 2024-11-15 23:16:03

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

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

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

You should ask your printer vendor (Xerox) for their specifications regarding the scope of JDF support for their DocuSp printers.

You may be lucky and get the info.

There is no other standardized way of job ticketing than JDF. There are several other vendor-specific ways, and Xerox may well have their own. Ask them.

浅笑轻吟梦一曲 2024-11-15 23:16:03

我在 施乐支持论坛

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

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

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

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

我已经测试了这个方法,它按预期工作:-)。将一些任意 XML 数据附加到 PDF 文件的开头会导致该文件无法在 Adob​​e Acrobat 中打开。但令人惊讶的是,此类文件在 Evince 文档查看器中打开得很好。

I received this response from "RogerK-Xerox" on the Xerox support forum.

Xerox uses an XML based ticketing system called Xerox Printing Instruction Format (XPIF). You can get an idea of how this format works by opening your Xerox custom print driver, programming some printing attributes, and then exporting the Xerox Job Ticket. This is accomplished by selecting the Advanced tab on the print driver, selecting the '+' next the Xerox Job Ticket and choosing 'Export Xerox Job Ticket...' and then pressing the 'Export...' button.

In order to get full access the the XPIF programming guide I believe that you have to register on http://www.xerox-solutions.net/Partners

I tried the above, and it did produce an XML file with job ticket instructions, which could presumably be re-loaded in the print driver. Now I'm looking for a way to use these files with printer hot folders, which is more in line with our current work-flow. The printer would need to know somehow which XPIF ticket belonged with which PDF file.

It seems that the XPIF file can be added to the beginning of a PDF file by simply concatenating the two files. The file can then be dragged into a hotfolder and the Xerox printer knows how to separate a job ticket from PDF.

I have tested this method, and it works as expected :-). Appending some arbitrary XML data to the beginning of a PDF file renders it un-openable in Adobe Acrobat. Surprisingly though, such files open just fine in Evince Document Viewer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文