Изберете източник на хартия в решение за печат на php

Здравейте, имам PHP решения за печат, използващи сокети. Използване на тази функция/клас.

public function printJob($queue){

        //Private static function prints waiting jobs on the queue.
        $this->printWaiting($queue);

        //Open a new connection to send the control file and data.
        $stream = stream_socket_client("tcp://".$this->host.":".$this->port, $this->errNo, $this->errStr, $this->timeout);
        if(!$stream){
            return $this->errNo." (".$this->errStr.")";
        } else {

            $job = self::getJobId();//Get a new id for this job

            //Set printer to receive file
            fwrite($stream, chr(2).$queue."\n");
            $this->debug .= "Confirmation of receive cmd:".ord(fread($stream, 1))."\n";

            //Send Control file.
            (isset($_SERVER['SERVER_NAME'])) ? $server = $_SERVER['SERVER_NAME'] : $server = "me";//Might be CLI and not have _SERVER
            $ctrl = "H".$server."\nPphp\nfdfA".$job.$server."\n";
            fwrite($stream, chr(2).strlen($ctrl)." cfA".$job.$server."\n");
            $this->debug .= "Confirmation of sending of control file cmd:".ord(fread($stream, 1))."\n";

            fwrite($stream, $ctrl.chr(0)); //Write null to indicate end of stream
            $this->debug .= "Confirmation of sending of control file itself:".ord(fread($stream, 1))."\n";






            if (is_readable($this->data)){

                //It's a filename, rather than just some ascii text that needs printing.  Open and stream.
                if (strstr(strtolower($_ENV["OS"]), "windows")){
                    $this->debug .= "Operating system is Windows\n";
                    $data = fopen($this->data, "rb");//Force binary in Windows.
                } else {
                    $this->debug .= "Operating system is not Windows\n";
                    $data = fopen($this->data, "r");
                }

                fwrite($stream, chr(3).filesize($this->data)." dfA".$job.$server."\n");
                $this->debug .= "Confirmation of sending receive data cmd:".ord(fread($stream, 1))."\n";

                while(!feof($data)){
                    fwrite($stream, fread($data, 8192));                     
                }
                fwrite($stream, chr(0));//Write null to indicate end of stream
                $this->debug .= "Confirmation of sending data:".ord(fread($stream, 1))."\n"; 

                fclose($data);

            } else {                      

                //Send data string
                fwrite($stream, chr(3).strlen($this->data)." dfA".$job.$server."\n");           
                $this->debug .= "Confirmation of sending receive data cmd:".ord(fread($stream, 1))."\n";

                fwrite($stream, $this->data.chr(0)); //Write null to indicate end of stream
                $this->debug .= "Confirmation of sending data:".ord(fread($stream, 1))."\n"; 

            }
        }

    }

Всичко е наред с него, но изглежда не мога да контролирам източника на хартия/тавата, която след това принтерът избира. Някой знае ли как се прави това?

Или може би различно решение, което използвам, харесвам това, защото мога да изпратя ip адреса (няма нужда от инсталиране), postscript файла и той се разпечатва. Така че, ако има друго решение, което изисква същите неща, тогава мога да използвам това.

Използвам PHP, iis, windows. Ричард


person Richard Housham    schedule 15.06.2015    source източник
comment
Току-що прочетох малко и това изглежда интересно.stackoverflow.com/questions/25280522/ забележителни функциите PSDocOptions и PSPageOptions   -  person Richard Housham    schedule 18.06.2015


Отговори (2)


Мисля, че това е по-скоро въпрос относно системата за печат на операционната система, която използвате (изглежда не казвате какво е това). Също така не мога да видя къде се извършва заданието за печат, това C# код ли е?

Всички принтери имат свойства, в които са включени неща като настройката на тавата. Когато печатате, трябва да конфигурирате устройството, стъпките за това ще бъдат различни за всяка операционна система. Например в Windows 8+ ще трябва да настроите билет за работа. Не си спомням точно как се прави на по-ранни версии на Windows, някаква сложна структура, доколкото си спомням. В Linux ще зависи дали използвате CUPS, ако използвате, вероятно ще трябва да настроите CUPS тръбопровод за конкретната тава, която искате да използвате.

Виждам, че има тестване на код, за да се види дали операционната система е Windows или нещо друго. Предполагам, че ще трябва да разберете какво да правите там.

[добавено по-късно]

Добре, сега разбирам по-добре какво правиш. Тъй като използвате Ghostscript за създаване на PostScript от вашия PDF файл, въпросът наистина има повече смисъл.

Връзката, която отбелязахте по-горе и PSDocOptions и PSPageOptions е това, от което се нуждаете, съчетано с точките на luser_droog относно избора на тава.

Така че първо трябва да разберете какво очаква вашият принтер по отношение на PostScript, за да смените тавите. Вашият PPD файл съдържа следното:

*InputSlot Internal/Cassette 1 (Internal): "<</ManualFeed false>> setpagedevice statusdict begin 0 setpapertray end"
*InputSlot PF60A/Cassette 2: "<</ManualFeed false>> setpagedevice statusdict begin 1 setpapertray end"
*InputSlot PF60B/Cassette 3: "<</ManualFeed false>> setpagedevice statusdict begin 4 setpapertray end"
*InputSlot PF60C/Cassette 4: "<</ManualFeed false>> setpagedevice statusdict begin 5 setpapertray end"
*InputSlot EF1/Envelope Feeder: "<</ManualFeed false>> setpagedevice statusdict begin 2 setpapertray end"

Така че, за да изберете "касета" 1, необходимият PostScript е:

<</ManualFeed false>> setpagedevice statusdict begin 0 setpapertray end

Ако сега приемем, че използвате последна версия на Ghostscript (т.е. поне версия 9.16), след това можете да добавите като част от вашия PDF към командния ред на PostScript;

-dPSDocOptions="<</ManualFeed false>> setpagedevice statusdict begin 0 setpapertray end"

Което ще зададе текущата тава на тава 1, преди да започне заданието. Имайте предвид, че вашият PostScript файл вече не е независим от устройството, сега ще работи надеждно само на този клас принтери.

Ако искате (например) страница 1 да бъде отпечатана на касета 1 и страница 2 на касета 2, трябва да използвате PSPageOptions, например:

    -dPSpageOptions=["<</ManualFeed false>> setpagedevice statusdict begin 0 setpapertray end"
 "<</ManualFeed false>> setpagedevice statusdict begin 1 setpapertray end"]

Предполагам, че внедрявате това в определена организация, а не отворена към света. Все пак може да е добре да поставите бележка някъде, че Ghostscript е лицензиран от AGPL и ако това някога е било предоставено като обща услуга, вероятно ще трябва да бъде предоставен целият изходен код (AGPL обхваща софтуера като услуга).

person KenS    schedule 18.06.2015
comment
Здравейте, това е фрагмент от PHP код. Това е IIS, така че това е windows. Текущата настройка е генериране на PDF във php (mpdf). Използвайте ghostscript (комаден ред), за да създадете PS скрипт, изпратен до принтера, използвайки IP адрес. Тогава не е необходимо принтерът да бъде инсталиран на сървъра. Това е за бизнес с много принтери, така че да е лесно. Мисля, че имам решение в тази връзка (bugs.ghostscript по-горе). Трябва да се сдобия с принтер за тестване (трябваше да е стъпка 1, съжалявам) и ще публикувам обратно с резултатите/отговора. - person Richard Housham; 18.06.2015
comment
Уау магия. знаете вашия ghostscript. Само като продължение и за пълно изглаждане на отговора. Въпросът ми е какво би било, ако имах x страници и исках всичките да са в тава 2. Ще ми трябват ли няколко <</ManualFeed false>> setpagedevice statusdict begin 1 setpapertray end по една за всяка страница? - person Richard Housham; 18.06.2015
comment
Не, ако това е настройка за целия документ, можете да използвате -dPSDocOptions. PSPageOptions работи по един на страница (така че запис 1 в масива е прикрепен към страница 1, запис 2 към страница 2 и т.н.). Когато достигне края на масива, той се обвива. Така че, ако искате настройките да се прилагат към нечетни и четни страници, трябва да предоставите само нечетните и след това четните опции. Това ще приложи запис 1 към страница 1, запис 2 към страница 2, запис 1 към страница 3 и т.н. Между другото, синтаксисът в отговора може да не е правилен, това работи от паметта, което е особено ненадеждно за мен. Той е документиран в ps2ps2.htm в директорията gs/doc. - person KenS; 18.06.2015
comment
наздраве за това, ще трябва да направя известно време в края на деня. Но ти ме насочи на правилния път и ми даде правилните променливи, които да разгледам. За това ще приема този отговор. Когато го накарам да работи, ще добавя лентите, които съм използвал, но това е специфично нещо за принтера в края на деня, така че не можете да знаете това от паметта! Благодаря за цялата ви помощ - person Richard Housham; 18.06.2015
comment
Най-накрая стигнах до това, опитвам се да направя C:\Program Files (x86)\gs\gs9.15\bin\gswin32.exe -dPSDocOptions=‹‹/ManualFeed false›› setpagedevice statusdict begin 0 setpapertray end - dNOPAUSE -dBATCH -sDEVICE=ps2write -sOutputFile=... inputfile.pdf - по различни различни начини (-sPSDocOptions) премахване на интервала и т.н. - нищо - получавам грешка -dName= трябва да бъде последвано от валиден токен. Идеи? - person Richard Housham; 29.06.2015
comment
Може да е бъг :-) Мисля, че така или иначе ще трябва да бъде -s, а не -d, тъй като това няма да приема произволни низове IIRC. - person KenS; 29.06.2015
comment
Да, изглежда така, знаете ли къде трябва да отиде низът във файла на P. Така че мога просто да заменя str или нещо подобно - person Richard Housham; 29.06.2015
comment
На документ, в главата трябва да е ОК, на страница, трябва да отиде някъде конкретно, забравих къде. Най-добрият ви залог ще бъде да отворите доклад за грешка. - person KenS; 29.06.2015
comment
Добре, добавен е доклад за грешка в очакване на отговор. В крайна сметка току-що добавен в ‹‹/ManualFeed false›› setpagedevice statusdict begin 1 setpapertray end Snippet след 1st %% BeginPageSetup Job done. - person Richard Housham; 30.06.2015

Това ще изисква специфичен за принтера postscript код. Трябва да търсите .PPD файлове (дефиниция на принтер postscript) за конкретните принтери, които трябва да използвате.

.ppd файловете са ASCII текст в специален формат, но лесни за четене от хора. Всички специални възможности на принтера, които не могат да бъдат направени в стандартен постскрипт (но все още постижими с постскрипт), се документират по този начин.

Правил съм подобен стил на печат в миналото, като използвах командата unix telnet, указвайки ip-адреса и порта, и пренасочвайки входа към моя ps файл. Същото би трябвало да е възможно с обвивката на Windows, използвайки telnet програма от командния ред.

person luser droog    schedule 17.06.2015
comment
Здравейте, благодаря за отговора - просто се опитвам да разбера какво казвате. Имам своя postscript файл - проверете. Имам своя ppd файл - връзка. openprinting.org/download/PPD/Kyocera/en/ Искате да кажете, че след това трябва да поставя спецификацията от ppd файла в моя ps файл. Използвам ghostscript (команден ред) мога ли да използвам това, за да ми помогне? Наздраве за вашата помощ. - person Richard Housham; 18.06.2015
comment
Допълнително четене тук, bugs.ghostscript.com/show_bug.cgi?id=690182 Може да е отговорът......... Времето ще покаже - person Richard Housham; 18.06.2015