biz-Streamマニュアル Webサービスサーバ ガイド 第12章 サンプルプログラム(.NET) 12.10 PDFを生成しバッチ印刷するサンプル(WCF)

12.10 PDFを生成しバッチ印刷するサンプル(WCF)

概要

PDFを生成しバッチ印刷するサンプルプログラムです。

このサンプルでは、印刷指示を行った後、「ジョブID」「印刷状態」を取得します。その結果「バッチ印刷エラーコード」を検知した場合は印刷の再実行を行います。 異常終了や例外を検知した場合はそこでプログラムを終了します。


環境準備

事前に『2.7 クライアントアプリケーションの環境構築』を確認してください。


サンプル構成

項目 ファイルパス
ページレイアウトサンプル <bswss-client_home>/sample/xml/Sample1.xml サンプル1
ソースサンプル <bswss-client_home>/sample/dotNET/wcf/WSS_WCF_Sample10.aspx.cs サンプル1

ソースサンプル



using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Web;
using BizStreamWebApplication.BizStreamServiceReference;

namespace BizStreamWebApplication
{
    public partial class WSS_WCF_Sample10 : System.Web.UI.Page
    {
        // Webサービスサーバのホスト名
        const string WSS_HOST_NAME = "wsssrv";

        // バッチ印刷サーバのホスト名
        const string PRINT_HOST_NAME = "prntsrv";

        // バッチ印刷サーバのポート番号
        const string PORT_NO = "3000";

        // プリンタ名
        const string PRINTER_NAME = "Bullzip PDF Printer";

        // 印刷状態の取得間隔(単位:ミリ秒)
        // 【注意】1000ミリ秒未満はバッチ印刷サーバに負荷が掛かるため短くしすぎないこと
        const int INTERVAL = 1 * 1000;

        // Webサービスサーバ上のサンプルディレクトリの場所
        const string WSS_BIZSTREAM_SAMPLE_DIR = "\\bs\\sample";

        // Webサービスのエンドポイントプリフィックス
        const string WSS_SERVICE_LOCATION = "http://" + WSS_HOST_NAME + ":8080/axis2/services";

        // BASIC認証のユーザ名
        const string USER_NAME = @"bizuser1";

        // BASIC認証のパスワード
        const string PASSWORD = @"bizuser1";

        // 監査ロギング用のユーザ定義
        const string USER_DEF = "AAA";

        // 入力レイアウト定義ファイル名
        const string LAYOUT_FILE = WSS_BIZSTREAM_SAMPLE_DIR + "\\xml\\Sample1.xml";

        // 印刷サービスのエンドポイントプリフィックス
        const string PRINT_SERVICE_LOCATION = "http://" + PRINT_HOST_NAME + ":" + PORT_NO;


        // 連続印刷数
        const int LOOP = 1;


        protected void Page_Load(object sender, EventArgs e)
        {
            // ブラウザに結果を表示
            Response.Clear();
            Response.ContentType = "text/html;charset=UTF-8";
            Response.Write("<HTML><HEAD><TITLE>WSS_WCF_Sample10</TITLE></HEAD><BODY>");
            Response.Flush();

            // 連続印刷をシミュレーションする
            for (int i = 0; i < LOOP; i++)
            {
                DoPrintAndGetStatus(sender, e);
            }

            // ブラウザに結果を表示
            Response.Write("<BR></BODY></HTML>");
            Response.Flush();
            HttpContext.Current.ApplicationInstance.CompleteRequest();
        }

        //  1回のバッチ印刷を行い、その印刷状態を監視する
        private void DoPrintAndGetStatus(object sender, EventArgs e)
        {
            // 印刷のループ
            // 通常は1回で抜けるが、PDF生成からやり直した場合は複数回ループする
            PRINT_LOOP: while (true)
            {
                generateOutputDataResponse dataResponse = null;
                try
                {
                    // PDF生成とバッチ印刷サーバへの送信を行う
                    dataResponse = DoPrint();
                }
                catch (TimeoutException ex)
                {
                    // 以下の場合に該当
                    // ・バッチ印刷が印刷要求を受け付けられなかった場合

                    System.Diagnostics.Debug.WriteLine("【エラー1】バッチ印刷の印刷要求結果を取得できませんでした。再度PDF生成からやり直します。" + ex.Message);
                    // 待ち時間の後、再度印刷要求を行う
                    Sleep();
                    goto PRINT_LOOP;
                }
                catch (Exception ex)
                {
                    // 以下の場合に該当
                    // ・PDF生成でエラーが発生した場合

                    // エラー処理をして異常終了とする
                    throw new Exception("【エラー2】PDF生成でエラーが発生しました。プログラムを終了します。", ex);
                }

                // 印刷状態取得のためjobIDを取得
                printResult prnResult = dataResponse.printResult;
                string jobId = prnResult.jobId;

                System.Diagnostics.Debug.WriteLine("==============================");
                System.Diagnostics.Debug.WriteLine("jobId=" + jobId);
                System.Diagnostics.Debug.WriteLine("==============================");

                if (String.IsNullOrEmpty(jobId))
                {
                    // 以下の場合に該当
                    // ・バッチ印刷が起動していない場合
                    // ・接続先が誤っている場合
                    // ・バッチ印刷が印刷要求を受け付けられない場合

                    System.Diagnostics.Debug.WriteLine("【エラー3】バッチ印刷の印刷要求結果を取得できませんでした。再度PDF生成からやり直します。");
                    // 待ち時間の後、再度印刷要求を行う
                    Sleep();
                    goto PRINT_LOOP;
                }

                // 待ち時間の後、印刷状態取得を行う
                Sleep();

                // 印刷状態取得ループ
                // ステータスコードが0006になるまでINTERVAL間隔で印刷状態取得を繰り返す
                STATUS_LOOP: while (true)
                {
                    // 印刷状態を取得する
                    printStatus prnStatus = null;
                    try
                    {
                        prnStatus = GetBatchPrintStatus(jobId);
                    }
                    catch (TimeoutException ex)
                    {
                        // 以下の場合に該当
                        // ・バッチ印刷が印刷状態要求を受け付けられなかった場合

                        // 【注意】
                        // このパターンは印刷状態取得に失敗するが、印刷成功・失敗は不定となる
                        // PDF生成からやり直した場合、二重に印刷されてしまう可能性があるため注意
                        // 厳密に印刷結果を管理するには異常終了としてプログラムを止めた後に出力結果を確認、未印刷分からやり直すこと

                        // 二重に印刷される可能性を許容する場合はこちらのロジックを使用する
                        System.Diagnostics.Debug.WriteLine("【エラー4】バッチ印刷の印刷状態を取得できませんでした。再度PDF生成からやり直します。" + ex.Message);
                        // 待ち時間の後、再度印刷要求を行う
                        Sleep();
                        goto PRINT_LOOP;

                        // 厳密に出力を管理するにはこちらのロジックを使用する
                        // エラー処理をして異常終了とする
                        // throw new Exception("【エラー4】バッチ印刷の印刷状態を取得できませんでした。プログラムを終了します。", ex);
                    }

                    if (prnStatus == null)
                    {
                        // 以下の場合に該当
                        // ・バッチ印刷が印刷状態要求を受け付けられなかった場合 (ソケット通信エラー)

                        // 【注意】
                        // このパターンは印刷状態取得に失敗するが、印刷成功・失敗は不定となる
                        // PDF生成からやり直した場合、二重に印刷されてしまう可能性があるため注意
                        // 厳密に印刷結果を管理するには異常終了としてプログラムを止めた後に出力結果を確認、未印刷分からやり直すこと

                        // 二重に印刷される可能性を許容する場合はこちらのロジックを使用する
                        System.Diagnostics.Debug.WriteLine("【エラー5】バッチ印刷の印刷状態を取得できませんでした。再度PDF生成からやり直します。");
                        // 待ち時間の後、再度印刷要求を行う
                        Sleep();
                        goto PRINT_LOOP;

                        // 厳密に出力を管理するにはこちらのロジックを使用する
                        // エラー処理をして異常終了とする
                        // throw new Exception("【エラー5】バッチ印刷の印刷状態を取得できませんでした。プログラムを終了します。");
                    }

                    // 情報取得日時
                    string dateTime = prnStatus.dateTime;

                    // エラー情報
                    error err = prnStatus.error;
                    string errorCause = err.cause;
                    string errorCode = err.code;
                    string errorDetails = err.details;

                    // ステータス
                    status st = prnStatus.status;
                    string stat = st.Value;
                    string statCode = st.code;

                    // プリンタ情報
                    printer prn = prnStatus.printer;
                    string printerName = prn.name;
                    string jobName = prn.jobName;

                    System.Diagnostics.Debug.WriteLine("------------------------------");
                    System.Diagnostics.Debug.WriteLine("dateTime=" + dateTime);
                    System.Diagnostics.Debug.WriteLine("errorCause=" + errorCause);
                    System.Diagnostics.Debug.WriteLine("errorCode=" + errorCode);
                    System.Diagnostics.Debug.WriteLine("errorDetails=" + errorDetails);
                    System.Diagnostics.Debug.WriteLine("jobId=" + jobId);
                    System.Diagnostics.Debug.WriteLine("jobName=" + jobName);
                    System.Diagnostics.Debug.WriteLine("printerName=" + printerName);
                    System.Diagnostics.Debug.WriteLine("status=" + stat);
                    System.Diagnostics.Debug.WriteLine("statusCode=" + statCode);
                    System.Diagnostics.Debug.WriteLine("------------------------------");

                    if (errorCode != null && (errorCode.Equals("114") || errorCode.Equals("405") || errorCode.Equals("506")))
                    {
                        // 以下の場合に該当
                        // 114=バッチ印刷のキュー上限に達した場合
                        // 405=スプールタイムアウトが発生した場合
                        // 506=指定したJobIDに対応する印刷状態が存在しない場合(バッチ印刷が再起動された場合など)
                        System.Diagnostics.Debug.WriteLine("【エラー6】バッチ印刷でエラーが発生しました。再度PDF生成からやり直します。エラーコード: " + errorCode + ", エラーメッセージ: " + errorDetails);

                        // 待ち時間の後、再度印刷要求を行う
                        Sleep();
                        goto PRINT_LOOP;
                    }

                    if (String.IsNullOrEmpty(statCode))
                    {
                        // 以下の場合に該当
                        // ・バッチ印刷が印刷要求または印刷状態要求を受け付けられない場合
                        // ・印刷状態最大保持数、印刷状態最大保持時間の値が小さく、印刷状態がクリアされてしまった場合

                        // 【注意】
                        // このパターンは印刷状態取得に失敗するが、印刷成功・失敗は不定となる
                        // PDF生成からやり直した場合、二重に印刷されてしまう可能性があるため注意
                        // 厳密に印刷結果を管理するには異常終了としてプログラムを止めた後に出力結果を確認、未印刷分からやり直すこと

                        // 二重に印刷される可能性を許容する場合はこちらのロジックを使用する
                        System.Diagnostics.Debug.WriteLine("【エラー6】バッチ印刷の印刷状態を取得できませんでした。再度PDF生成からやり直します。");
                        // 待ち時間の後、再度印刷要求を行う
                        Sleep();
                        goto PRINT_LOOP;

                        // 厳密に出力を管理するにはこちらのロジックを使用する
                        // エラー処理をして異常終了とする
                        // throw new Exception("【エラー6】バッチ印刷の印刷状態を取得できませんでした。プログラムを終了します。");
                    }
                    else if (statCode.Equals("0002") || statCode.Equals("0004"))
                    {
                        // 0002 (印刷指示受付)
                        // 0004 (印刷中)

                        // 以下の場合に該当
                        // ・バッチ印刷のキューに存在するが、キュー取り出し待ち状態の場合
                        // ・キューから取り出されてAdobeモジュールによるPDFロードが行われ、プリントスプーラへ入るまでの間の場合

                        // 待ち時間の後、再度印刷状態取得を実施
                        Sleep();
                        goto STATUS_LOOP;
                    }
                    else if (statCode.Equals("0006"))
                    {
                        // 0006 (印刷要求送信完了)

                        // 以下の場合に該当
                        // ・正常にプリントスプーラへ送信完了した場合
                        System.Diagnostics.Debug.WriteLine("【正常】プリントスプーラへの送信が完了しました。JobID: " + jobId);

                        // ブラウザに結果を表示
                        Response.Write("<BR>STATUS = " + stat);
                        Response.Write("<BR>STATUS_CODE = " + statCode);
                        Response.Write("<BR>DATE_TIME = " + dateTime);
                        Response.Write("<BR>PRINTER_NAME = " + printerName);
                        Response.Write("<BR>JOB_NAME = " + jobName);
                        Response.Write("<BR>ERROR_CODE = " + errorCode);
                        Response.Write("<BR>ERROR_CAUSE = " + errorCause);
                        Response.Write("<BR>ERROR_DETAILS = " + errorDetails);
                        Response.Write("<HR>");
                        Response.Flush();

                        goto PRINT_LOOP_END;
                    }
                    else if (statCode.Equals("0008"))
                    {
                        // 0008 (印刷異常終了)

                        if (errorCode != null && errorCode.Equals("000"))
                        {
                            // 以下の場合に該当
                            // ・印刷状態は0008で確定しているがエラーコードが確定するまでの間に印刷状態取得が行われた場合

                            // 待ち時間の後、再度印刷状態取得を行う
                            Sleep();
                            goto STATUS_LOOP;
                        }
                        else if (errorCode != null && errorCode.Equals("405"))
                        {
                            // 以下の場合に該当
                            // 405=スプールタイムアウトが発生した場合
                            System.Diagnostics.Debug.WriteLine("【エラー7】バッチ印刷でエラーが発生しました。再度PDF生成からやり直します。エラーコード: " + errorCode + ", エラーメッセージ: " + errorDetails);

                            // 待ち時間の後、再度印刷要求を行う
                            Sleep();
                            goto PRINT_LOOP;
                        }
                        else
                        {
                            // 以下の場合に該当
                            // ・AdobeモジュールによるPDFロード、またはプリントスプーラへの投入時にエラーが発生した場合

                            // エラー処理をして異常終了とする
                            throw new Exception("【エラー8】印刷異常終了となりました。プログラムを終了します。");
                        }
                    }
                }
            }
        PRINT_LOOP_END:;
        }

        // PDFを生成してバッチ印刷を実行する
        private generateOutputDataResponse DoPrint()
        {
            // クライアントを生成
            bizstreamPortTypeClient client =
                new bizstreamPortTypeClient("BizstreamSOAP11port",
                    WSS_SERVICE_LOCATION + "/bizstream?UserDef=" + USER_DEF);

            // 認証の設定
            BindingElementCollection elements = client.Endpoint.Binding.CreateBindingElements();
            elements.Find<HttpTransportBindingElement>().AuthenticationScheme =
                System.Net.AuthenticationSchemes.Basic;
            client.ClientCredentials.UserName.UserName = USER_NAME;
            client.ClientCredentials.UserName.Password = PASSWORD;

            // MTOMを有効化
            elements.Remove<TextMessageEncodingBindingElement>();
            MtomMessageEncodingBindingElement mtom = new MtomMessageEncodingBindingElement();
            mtom.ReaderQuotas.MaxStringContentLength = 100000;
            elements.Insert(0, mtom);
            elements.Find<HttpTransportBindingElement>().KeepAliveEnabled = false;
            client.Endpoint.Binding = new CustomBinding(elements);

            // リクエストメッセージの作成
            generateOutputDataRequest request = new generateOutputDataRequest();

            // バッチ印刷の出力を設定
            output outPut = new output();
            batchPrint batchPrint = new batchPrint();
            doPrint doPrint = new doPrint();
            printer prn = new printer();
            doPrint.url = PRINT_SERVICE_LOCATION;
            batchPrint.doPrint = doPrint;
            // プリンタ名
            prn.name = PRINTER_NAME;
            // 印刷部数
            prn.numberOfCopy = "1";
            // 出力トレイ
            prn.selectedTray = "AUTO";
            // 印刷識別子(2バイト文字を使用する場合はUTF-8)
            prn.jobName = "WSS_WCF_Sample10";
            // 開始ページ番号
            prn.fromPage = "1";
            // 終了ページ番号
            prn.toPage = "-1";
            // 用紙に合わせて印刷
            prn.doFit = "true";
            // 暗号化パスワード(バッチ印刷インストーラで指定したもの)
            // prn.password = "password";
            // エンコード済み暗号化パスワード
            // prn.passwordWithEncoded = "cGFzc3dvcmQ=";

            batchPrint.printer = prn;
            outPut.Item = batchPrint;
            request.output = outPut;

            // レイアウト定義を設定
            request.layoutData = new layoutDefinition[1];
            request.layoutData[0] = new layoutDefinition();
            request.layoutData[0].uri = LAYOUT_FILE;

            // リクエストを送信
            return client.generateOutputData(request);
        }

        // 指定したJobIDをキーとして印刷状態を取得する
        private printStatus GetBatchPrintStatus(String jobID)
        {
            // クライアントを生成
            bizstreamPortTypeClient client =
                new bizstreamPortTypeClient("BizstreamSOAP11port",
                    WSS_SERVICE_LOCATION + "/bizstream?UserDef=" + USER_DEF);

            // 認証の設定
            BindingElementCollection elements = client.Endpoint.Binding.CreateBindingElements();
            elements.Find<HttpTransportBindingElement>().AuthenticationScheme =
                System.Net.AuthenticationSchemes.Basic;
            client.ClientCredentials.UserName.UserName = USER_NAME;
            client.ClientCredentials.UserName.Password = PASSWORD;

            // MTOMを有効化
            elements.Remove<TextMessageEncodingBindingElement>();
            MtomMessageEncodingBindingElement mtom = new MtomMessageEncodingBindingElement();
            mtom.ReaderQuotas.MaxStringContentLength = 100000;
            elements.Insert(0, mtom);
            elements.Find<HttpTransportBindingElement>().KeepAliveEnabled = false;
            client.Endpoint.Binding = new CustomBinding(elements);

            // JobIDを設定
            query qry = new query();
            qry.url = PRINT_SERVICE_LOCATION;
            string[] array = new string[1];
            array[0] = jobID;
            qry.jobId = array;

            // リクエストを送信
            queryResult queryResult = client.getBatchStatus(qry);

            // 印刷状態を取得
            printStatus[] printStatuses = queryResult.printStatuses;
            if (printStatuses.Length < 1)
            {
                return null;
            }
            printStatus prnStatus = printStatuses[0];

            return prnStatus;
        }

        // 指定した時間待つ
        private void Sleep()
        {
            System.Threading.Thread.Sleep(INTERVAL);
        }
    }
}