.NETドライバはC#で書かれており、C#, VB.NETなどから利用することができます。 ストリーム(System.IO.Stream)からストリームへの変換に対応しており、巨大な文書も容易に変換することができます。
また、ASP.NETで利用する際は、ASP.NETからの出力をキャプチャしながら、変換結果を送り出すことができます。 これにより、PDFの出力も普通のウェブページと同様にASP.NETにより作ることができます。
.NET用ドライバはCopper PDF本体とは別に配布されています。 http://sourceforge.jp/projects/copper/releases/?package_id=12608 からcti-dotnet_2.x.x.zipをダウンロードしてください。 このアーカイブに含まれるCTI.dllをアプリケーションのディレクトリまたはシステムディレクトリ(C:\WINDOWS\system32)に配置してください。
ドライバの窓口となるクラスはCTI.DriverManagerです。 例えばlocalhostの8099番ポートで起動しているcopperdに、ユーザーID"user"、パスワード"kappa"で接続するには、以下のようにします。
using System; using CTI; ... using (Session session = DriverManager.getSession(new Uri("ctip://localhost:8099/"), "user", "kappa")) { //各種操作 ... } ...
.NET版ドライバ2.0.1以降から、一定時間通信がない状態で自動的に通信を切断するタイムアウトに対応しています。
以下のようにURLパラメータで、timeoutをミリ秒単位で指定できます。
ctip://127.0.0.1:8099/?timeout=10000
ここではAPIによるアクセスの概要で説明した各手順に対応する関数を列挙します。 各関数の詳細はドライバのapidoc/htmlディレクトリ内のAPIドキュメントか、 オンラインのAPIドキュメントを参照してください。
次の例は、サーバー側からネットワーク上のウェブページアクセスしてPDFに変換します。
using System; using Zamasoft.CTI; namespace examples { /// <summary> /// サーバー側からインターネット上の文書にアクセスして変換します。 /// </summary> class ServerResource { static void Main(string[] args) { using (Session session = DriverManager.getSession(new Uri("ctip://localhost:8099/"), "user", "kappa")) { // test.pdfに結果を出力する Utils.SetResultFile(session, "test.pdf"); // http://copper-pdf.com/以下にあるリソースへのアクセスを許可する session.Property("input.include", "http://copper-pdf.com/**"); // ウェブページを変換 session.Transcode("http://copper-pdf.com/"); } } } }
Imports System Imports System.IO Imports Zamasoft.CTI ''' <summary> ''' サーバー側からインターネット上の文書にアクセスして変換します。 ''' </summary> Module ServerResource Sub Main() Using session As Session = DriverManager.getSession(New Uri("ctip://localhost:8099/"), "user", "kappa") ' test.pdfに結果を出力する Utils.SetResultFile(session, "test.pdf") ' http://copper-pdf.com/以下にあるリソースへのアクセスを許可する session.Property("input.include", "http://copper-pdf.com/**") ' ウェブページを変換 session.Transcode("http://copper-pdf.com/") End Using End Sub End Module
.NET版ドライバの特徴は、ASP.NETをPDF出力のためのテンプレートとして利用できるようになることです。 前準備として、以下のクラスを用意しておきます。
public class CopperPDF { // 結果を直接ブラウザに返すように設定します。 static public void SetResponse(Session session, HttpResponse response) { session.Results = new SingleResult(new ContentLengthSender(response)); } // Content-Lengthヘッダを送信するためのビルダー。 private class ContentLengthSender : Builder { private readonly HttpResponse response; public ContentLengthSender(HttpResponse response) : base(response.OutputStream) { this.response = response; } public override void Finish() { this.response.ContentType = this.info.MimeType; response.AppendHeader("Content-Length", this.length.ToString()); base.Finish(); } } }
Public Class CopperPDF ' 結果を直接ブラウザに返すように設定します。 Public Shared Sub SetResponse(session As Session, response As HttpResponse) session.Results = New SingleResult(New ContentLengthSender(response)) End Sub ' Content-Lengthヘッダを送信するためのビルダー。 Private Class ContentLengthSender Inherits Builder Private ReadOnly response As HttpResponse Sub New(response As HttpResponse) MyBase.New(response.OutputStream) Me.response = response End Sub Overrides Sub Finish() response.ContentType = Info.MimeType response.AppendHeader("Content-Length", length.ToString()) MyBase.Finish() End Sub End Class End Class
ASP.NETにより生成したPDFを直接ブラウザに送る場合、HTTPレスポンスのContent-Typeヘッダに"application/pdf"を設定し、 Content-LengthヘッダにPDFファイルのサイズを設定する必要があります。 上記のContentLengthSenderは、そのためのもので、親クラスのBuilderからPDFのMIME型(Info.MimeType)、ファイルサイズ(length)を得ています。
ASP.NETで、他のページをPDFのテンプレートとして利用するには、以下のようにします。
CopperPDF.SetResponse(session, Response); string template = Request.ApplicationPath + "PDFTemplate.aspx"; using (StreamWriter writer = new StreamWriter(session.Transcode(new SourceInfo(".")))) { Server.Execute(template, writer); }
CopperPDF.SetResponse(session, Response) Dim template As String = Request.ApplicationPath + "PDFTemplate.aspx" Using writer As New StreamWriter(session.Transcode(New SourceInfo("."))) Server.Execute(template, writer) End Using
上記の例ではPDFTemplate.aspxを実行した結果をCopper PDFに送り、変換した結果をブラウザに送信しています。 PDFTemplate.aspxは普通のASP.NETページなので、例えばPDF上にカレンダーを印刷するためにカレンダーコントロールを利用するといったことができます。
他のサンプルはドライバのCTIディレクトリに収められています。
結果の出力先、リソースの送信、ファイルの変換等のよく使われる操作が、 Zammasoft.CTI.Utils のstatic(Shared)メソッドにまとめられています。
例えば、事前に関連するCSSを送信してHTMLファイルを変換する処理は、次のように簡単に書けます。
... Utils.SendResourceFile(session, "test.css", "text/css", "UTF-8"); Utils.TranscodeFile(session, "test.html", "text/html", "UTF-8"); ...
... Utils.SendResourceFile(session, "test.css", "text/css", "UTF-8") Utils.TranscodeFile(session, "test.html", "text/html", "UTF-8") ...
出力先を変え、Transcodeメソッドを繰り返し呼び出すことで、 同じセッションで何度もドキュメントを変換することができます。 送信済みのリソース、設定済みのプロパティは同じセッションで維持されます。 同じセッションのまま初期状態に戻すには Reset を呼び出してください。
出力先が単一のファイルやストリームの場合は、Utilsの SetResultFile か、 SetResultStream を使ってください。 これらのメソッドは内部的にZamasoft.CTI.Result.SingleResultクラスを使用しています。
Zamasoft.CTI.Result.Resultsインターフェースは、 複数の出力結果を受け取るためのインターフェースです。 SessionのResultsプロパティにセットします。
複数の結果をファイルとして出力する場合は、 Zamasoft.CTI.Result.FileResults を使用してください。 このクラスは、指定したディレクトリに、1から開始する連番の前後に指定した文字列をくっつけたファイル名で結果を出力します。 次の例では変換結果の各ページを、resultsディレクトリ内に"image[通し番号].jpeg"という名前で別々のJPEG画像として出力します。
... session.Property("output.type", "image/jpeg"); session.Results = new FileResults("results/image", ".jpeg")); ...
... session.Property("output.type", "image/jpeg") session.Results = New FileResults("results/image", ".jpeg")) ...
さらに複雑な処理が必要な場合は、Resultsインターフェースを実装するクラスを用意する必要があります。 Resultsインターフェースを実装したクラスでは、 Zamasoft.CTI.Result.Builder を使ってストリームやファイルにデータを出力してください。
SessionのSourceResolverプロパティに ソースリゾルバ(Zamasoft.CTI.Source.SourceResolver) を設定すると、サーバーから要求されたリソースを都度送信できるようになります。
次の例のように、SourceResolverを実装すると、クライアント側のファイル、あるいはクライアント側からウェブにアクセスして取得したデータをサーバーに送ることができます。
class MySourceResolver : SourceResolver { public Stream Resolve(string _uri, ref SourceInfo info) { Uri uri = new Uri(_uri); if (uri.IsFile) { string file = uri.AbsolutePath; if (!File.Exists(file)) { return null; } info = new SourceInfo(_uri); return new FileStream(file, FileMode.Open, FileAccess.Read); } else if (uri.Scheme == "http") { WebRequest req = WebRequest.Create(uri); WebResponse resp = req.GetResponse(); info = new SourceInfo(_uri); info.MimeType = resp.Headers.Get("Content-Type"); return resp.GetResponseStream(); } return null; } }
Class MySourceResolver Implements SourceResolver Function Resolve(_uri As String, ByRef info As SourceInfo) As Stream Implements SourceResolver.Resolve Dim uri As New Uri(_uri) If uri.IsFile Then Dim file As String = uri.AbsolutePath If Not System.IO.File.Exists(file) Then Return Nothing End If info = New SourceInfo(_uri) Return New FileStream(file, FileMode.Open, FileAccess.Read) ElseIf uri.Scheme = "http" Then Dim req As WebRequest = WebRequest.Create(uri) Dim resp As WebResponse = req.GetResponse() info = New SourceInfo(_uri) info.MimeType = resp.Headers.Get("Content-Type") Return resp.GetResponseStream() End If Return Nothing End Function End Class
Sessionの Resource, Transcode メソッド等では、データの仮想URI、MIME型、キャラクタ・エンコーディング、予測されるデータサイズ。 SourceInfo クラスにより渡します。
複数の結果を結合したものを得るためには、 Continuous プロパティにtrueを設定した後、Transcodeを複数回呼び出し、最後に Join を呼び出してください。
... session.Continuous = true; Utils.SendResourceFile(session, "test.css", "text/css", "UTF-8"); Utils.TranscodeFile(session, "test.html", "text/html", "UTF-8"); session.Transcode("http://print.cssj.jp/"); session.Join(); ...
... session.Continuous = true Utils.SendResourceFile(session, "test.css", "text/css", "UTF-8") Utils.TranscodeFile(session, "test.html", "text/html", "UTF-8") session.Transcode("http://print.cssj.jp/") session.Join() ...
SessionのAbort メソッドは文書の変換処理を中断しますが、Transcodeメソッドは処理の間ブロックするため、別スレッドからAbortを呼び出す必要があります。 Abortは引数によって、強制的に中断するモードと、きりのよいところまで処理して、一応利用可能な結果を出力するモードの2つがあります。 後者のモードは、例えば大きなPDFファイルを出力中に処理を中断して、途中までの出力結果を見たい場合に有用です。 ただし、1ページ目を出力される前に中断してしまった場合など、読み込み可能なデータが出力できないことも起こり得ます。