HTTP/RESTインターフェースはCopper PDF 2.1.0からサポートされた、HTTPベースのインターフェースです。 高速・高機能なCTIPに比べて冗長なプロトコルですが、HTTPをベースとしているため、普通のウェブブラウザやHTTPクライアントライブラリを利用できる利点があります。
HTTP通信による処理速度の損失は、変換処理の開始・終了時に発生するものなので、数十ページ以上の文書の出力ではほとんど問題になりません。 数ページ程度の文書を繰り返し出力する場合は、処理速度はおおむね70%程度に低下します。
HTTP/RESTインターフェースはCTIP 2.0と同等の機能を備えており、実際にJava版のCTIP 2.0ドライバは、 CTIP, HTTP接続の両方で、同一のインターフェースを利用することができます。
このドキュメントでは、HTTP/RESTインターフェースの基本的な使用方法だけを解説します。
HTTP/RESTインターフェースの完全な仕様は、以下のアドレスで公開している仕様書を参照してください。
https://osdn.net/projects/copper/docs/cti-rest-v1
HTTP/RESTインターフェースにより、Copper PDFに対して何らかの動作(アクション)の実行を要求するためには、 HTTPのGETまたはPOSTメソッドでクライアントからアクセスします。 アクションの種類は、ファイルパスにより識別されます。 処理対象文書や認証情報など、必要な情報はリクエストパラメータとして送ります。 アクションとファイルパスの対応と、使用可能なリクエストパラメータの表は以下の通りです。
パス | リクエストパラメータ | 説明 |
---|---|---|
/open | rest.user rest.password rest.timeout rest.httpSession |
セッションの開始 |
/info | rest.id rest.user rest.password rest.uri |
サーバーの情報(セッションの開始と終了を兼ねる) |
/properties | rest.id "rest."で始まらないパラメータ |
プロパティ設定 |
/resources | rest.id rest.uri rest.mimeType rest.encoding rest.resource rest.notFound "rest."で始まらないパラメータ |
リソース送信(プロパティ設定を兼ねる) |
/transcode | rest.id rest.user rest.password rest.async rest.requestResource "rest."で始まらないパラメータ rest.uri rest.mimeType rest.encoding rest.resource rest.main rest.mainURI |
ドキュメント変換処理(セッションの開始と終了、プロパティ設定、リソース送信を兼ねる) |
/messages | rest.id rest.wait |
メッセージ受信 |
/result | rest.id rest.uri |
ドキュメント変換結果受信 |
/abort | rest.id rest.mode |
ドキュメント変換処理の中断 |
/reset | rest.id |
リセット |
/close | rest.id |
セッションの終了 |
例えばlocalhostの8097ポートでドキュメント変換サーバーが動作している場合、変換処理を実行するには、 http://localhost:8097/transcode にアクセスします。
HTTP/RESTインターフェースの機能をフルに活用する場合は、openによりセッションを開始し、各種操作をした後、closeによりセッションを終了することが基本となります。 ただし、transcodeアクションは簡単な変換処理であれば1回のリクエストだけで完結できるようになっています。
リクエストパラメータは、クエリパラメータで送る方法、POSTメソッドのフォームパラメータとして送る方法(application/x-www-form-urlencoded)、 そしてmultipart/form-data形式のファイルとフォームフィールドとして送る方法があります (さらに、ファイルそのものをリクエストボディとして送る方法があります。詳細は仕様書を参照してください)。
application/x-www-form-urlencoded を使用する場合、送信できるデータの最大サイズに制限があります(190KB程度)。 そのため、アプリケーション側から変換対象のドキュメントをCopper PDFに送る場合は、なるべくmultipart/form-dataの使用を推奨します。
リクエストパラメータの意味は次の表の通りです。
パラメータ名 | 説明 |
---|---|
rest.user | 認証のためのユーザー名です。 |
rest.password | 認証のためのパスワードです。 |
rest.timeout | セッションの最小持続時間(ミリ秒)です。 |
rest.httpSession | trueを設定すると、クッキーによるHTTPセッション使用します。 |
rest.id | セッションを識別するIDです。クッキーによるHTTPセッション使用する場合は不要です。 |
rest.uri | infoアクションではサーバー情報の識別URI、resultアクションでは結果の識別URI、他のアクションでは次に送るデータの仮想URIを表します。 |
rest.mimeType | 次に送るデータのMIME型です。 |
rest.encoding | 次に送るデータのキャラクタ・エンコーディングです。 |
rest.resource | リソースデータです。これはmaltipart/form-dataのファイルとして送ることもできます。 |
rest.notFound | リソースデータの代わりに、このパラメータにtrueを設定すると、リソースが存在しないことを示します。 |
rest.async | transcodeアクションは通常、変換結果をレスポンスとして返しますが、 このパラメータにtrueを設定すると変換結果をresultアクションにより得ることを前提に、非同期的にドキュメント変換処理を実行します。 |
rest.requestResource | trueを設定すると、サーバーが必要なリソースをクライアントに要求するようになります。 クライアントはリソースの送信要求をmessagesアクションで確認する必要があります。 |
rest.main | 変換対象のメインドキュメントです。これはmaltipart/form-dataのファイルとして送ることもできます。 |
rest.mainURI | サーバーに変換対象のメインドキュメントを取得させる場合のURIです。 |
rest.wait | メッセージの変化があるまでmessagesアクションのレスポンスを保留する場合の最大待ち時間(ミリ秒)です。 |
rest.mode | 1であればなるべく有効なデータを出力して処理を中断し、2であればなるべく直ちに処理を中断します。 |
なお、各アクションのレスポンスの詳細は仕様書を参照してください。
ウェブブラウザからデータの変換を行う場合、最も簡単な方法は以下のフォームをHTMLファイルとして保存して (キャラクタ・エンコーディングはUTF-8にしてください)、ブラウザで表示し、「変換」ボタンを押すことです。 テキストエリアの内容(Hello world!)がPDF化されます。
<form action="http://localhost:8097/transcode"> <input type="hidden" name="rest.user" value="user"/> <input type="hidden" name="rest.password" value="kappa"/> <textarea name="rest.main"> <html><body>Hello world!</body></html> </textarea> <button type="submit">変換</button> </form>
アップロードしたファイルを変換することもできます。
<form action="http://localhost:8097/transcode" method="post" enctype="multipart/form-data"> <input type="hidden" name="rest.user" value="user"/> <input type="hidden" name="rest.password" value="kappa"/> <input type="file" name="rest.main" /> <button type="submit">変換</button> </form>
※新しく開発されたRubyインターフェースか、実行環境としてJRubyを使う場合はJavaインターフェースを利用した方がより高速です。
Rubyではhttpclientモジュールを使うと簡単です。 以下のサンプルでは、ヒアドキュメントとして記述したHTMLを変換します。
require 'httpclient' # 変換対象のHTML data = <<DATA <html> <body> RubyからCopper PDFを使う。 </body> </html> DATA # POSTの準備 client = HTTPClient.new postdata = { "rest.user" => "user", "rest.password" => "kappa", "rest.main" => data, } # 大きなデータを扱えるようにmultipart/formdataで送信(boundaryは適当な文字列) boundary = "3w48588hfwfdwed2332hdiuj2d3jiuhd32" puts client.post_content("http://localhost:8097/transcode", postdata, "content-type" => "multipart/form-data, boundary=#{boundary}")
以下の例では https://copper-pdf.com/ をPDF化します。 前の例では大きなデータをPOSTするため multipart/form-data を使用しましたが、POSTするデータが小さい場合は普通のPOST(application/x-www-form-urlencoded)で構いません。 パラメータの input.include画像等の取得のためにアクセスを許可するアドレスのパターンです。
require 'httpclient' # POSTの準備 client = HTTPClient.new postdata = { "rest.user" => "user", "rest.password" => "kappa", "input.include" => "https://copper-pdf.com/**", "rest.mainURI" => "https://copper-pdf.com/", } # POSTを実行 puts client.post_content("http://localhost:8097/transcode", postdata)
※新しく開発されたPythonインターフェースか、実行環境としてJythonを使う場合はJavaインターフェースを利用した方がより高速です。
Pythonではurllib2モジュールを使うことができます。 以下のサンプルでは、三重クォートで囲った文字列リテラルとして記述したHTMLを変換します。
# -*- coding: utf_8 -*- import urllib2 # multipart/form-dataの出力(boundaryは適当な文字列) boundary = '3w48588hfwfdwed2332hdiuj2d3jiuhd32' def multipart_formdata(form_dict): disposition = 'Content-Disposition: form-data; name="%s"' lines = [] for k, v in form_dict.iteritems(): lines.append('--' + boundary) lines.append(disposition % k) lines.append('') lines.append(v) lines.append("--" + boundary + "--") lines.append('') value = "\r\n".join(lines) return value # 変換対象のHTML data = """ <html> <body> PythonからCopper PDFを使う。 </body> </html> """ # POSTの実行 params = {'rest.user':'user', 'rest.password':'kappa', 'rest.main':data} url = 'http://localhost:8097/transcode' req = urllib2.Request(url) req.add_header("Content-Type", "multipart/form-data; boundary=" + boundary) data = multipart_formdata(params) f = urllib2.urlopen(req, data) # 結果表示 print f.read()
以下の例では https://copper-pdf.com をPDF化します。 前の例では大きなデータをPOSTするため multipart/form-data を使用しましたが、POSTするデータが小さい場合は普通のPOST(application/x-www-form-urlencoded)で構いません。 こちらはurllibを使っています。 パラメータの input.include画像等の取得のためにアクセスを許可するアドレスのパターンです。
# -*- coding: utf_8 -*- import urllib url = 'http://localhost:8097/transcode' params = urllib.urlencode({'rest.user':'user', 'rest.password':'kappa', 'input.include':'https://copper-pdf.com**', 'rest.mainURI':'https://copper-pdf.com', }) f = urllib.urlopen(url, params) print f.read()
※C# / VB.NETではRESTインターフェースを使用する必要はなくなりました。 より高速で高機能な.NETドライバの使用を推奨します。
C#では.NETのWebClientを使うことができます。 以下のサンプルでは、ヒアドキュメントとして記述したHTMLを変換します。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Collections.Specialized; namespace cti.net { class Program { static void Main(string[] args) { string data = @" <html> <body> C#からCopper PDFを使う。 </body> </html> "; WebClient client = new WebClient(); NameValueCollection par = new NameValueCollection(); par.Add("rest.user", "user"); par.Add("rest.password", "kappa"); par.Add("rest.main", data); byte[] res = client.UploadValues("http://localhost:8097/transcode", par); Console.OpenStandardOutput().Write(res, 0, res.Length); client.Dispose(); } } }
以下の例では https://copper-pdf.com をPDF化します。 パラメータの input.include 画像等の取得のためにアクセスを許可するアドレスのパターンです。
この例では、変換結果をストリームに逐次送り出すため、メモリを節約することができ、巨大なPDFの出力にも対応できます。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Collections.Specialized; namespace cti.net { class ServerDocument { static void Main(string[] args) { Response.ClearContent(); Response.ContentType = "application/pdf"; WebClient wc = new WebClient(); String uri = "http://localhost:8097/transcode" + // ローカルマシンのCopper PDF "?rest.user=user" + "&rest.password=kappa" + "&input.include=https://copper-pdf.com/**" + // 画像等へのアクセス許可 "&rest.mainURI=https://copper-pdf.com/"; // 変換対象アドレス Stream input = wc.OpenRead(uri); Stream output = Console.OpenStandardOutput(); byte[] buff = new byte[4096]; int len; while ((len = input.Read(buff, 0, buff.Length)) > 0) output.Write(buff, 0, len); input.Close(); wc.Dispose(); } } }
※C# / VB.NETではRESTインターフェースを使用する必要はなくなりました。 より高速で高機能な.NETドライバの使用を推奨します。
以下の例では https://copper-pdf.com/ をPDF化します。 それぞれC#とVisualBasicのプログラム例です。 パラメータの input.include 画像等の取得のためにアクセスを許可するアドレスのパターンです。
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Import Namespace="System.Net" %> <%@ Import Namespace="System.IO" %> <% Response.ClearContent(); Response.ContentType = "application/pdf"; // ファイル名 String filename = "FILENAME.pdf"; Response.AddHeader("Content-Disposition", "attachment; filename=" + filename); Response.ContentType = "application/pdf"; WebClient wc = new WebClient(); String uri = "http://localhost:8097/transcode" + // ローカルマシンのCopper PDF "?rest.user=user" + "&rest.password=kappa" + "&input.include=https://copper-pdf.com/**" + // 画像等へのアクセス許可 "&rest.mainURI=https://copper-pdf.com/"; // 変換対象アドレス Stream input = wc.OpenRead(uri); Stream output = Response.OutputStream; byte[] buff = new byte[4096]; int len; while ((len = input.Read(buff, 0, buff.Length)) > 0) output.Write(buff, 0, len); input.Close(); wc.Dispose(); %>
<%@ Page Language="VB" %> <%@ Import Namespace="System.Net" %> <%@ Import Namespace="System.IO" %> <% Response.ClearContent() Response.ContentType = "application/pdf" ' ファイル名 Dim filename As String = "FILENAME.pdf" Response.AddHeader("Content-Disposition", "attachment; filename=" + filename) Response.ContentType = "application/pdf" Dim wc As WebClient = New WebClient() ' ローカルマシンのCopper PDF Dim uri As String = "http://localhost:8097/transcode" uri &= "?rest.user=user" uri &= "&rest.password=kappa" ' 画像等へのアクセス許可 uri &= "&input.include=hhttps://copper-pdf.com/**" ' 変換対象アドレス uri &= "&rest.mainURI=https://copper-pdf.com/" Dim input As Stream = wc.OpenRead(uri) Dim output As Stream = Response.OutputStream Dim buff(4096) As Byte Dim len As Integer len = input.Read(buff, 0, buff.Length) While (len > 0) output.Write(buff, 0, len) len = input.Read(buff, 0, buff.Length) End While input.Close() wc.Dispose() %>
4th Dimension(4D)ではInternet CommandsのTCP/IPコマンドを使うことができます。 以下のサンプルでは、BLOBに格納したHTMLを変換します。
C_TEXT($host;$user;$password;$boundary;$sourceType;$source;$beforeContent;$afterContent;$resultFile;$text) C_LONGINT($port;$length;$err;$status;$socket;$pos) C_BLOB($content;$buffer;$data) C_TIME($doc) `Copper PDFサーバー $host:="localhost" $port:=8097 $user:="user" $password:="kappa" `変換対象HTML $sourceType:="text/html" $source:="<html><head><title>サンプル</title></head><body>4DからCopper PDFを使う。</body></html>" TEXT TO BLOB($source;$content) `BLOBに変換 `結果ファイル名 $resultFile:="Result.pdf" `通信開始 $err:=TCP_Open ($host;$port;$socket) $err:=TCP_State ($socket;$status) `リクエスト送信 $boundary:=String(Random)+String(Random)+String(Random) `マルチパートの境界(ランダムな文字列) $beforeContent:="---"+$boundary+"\r\n" $beforeContent:=$beforeContent+"Content-Disposition: form-data; name=\"rest.main\"; filename=\"data.html\"\r\n" $beforeContent:=$beforeContent+"Content-Type: "+$sourceType+"\r\n\r\n" $afterContent:="\r\n---"+$boundary+"--\r\n" $length:=Length($beforeContent)+BLOB size($content)+Length($afterContent) $err:=TCP_Send ($socket;"POST /transcode?rest.user="+$user+"&rest.password="+$password+" HTTP/1.0\r\n") `keep-aliveとchunkedを使わないためHTTP/1.0で接続する $err:=TCP_Send ($socket;"Host: "+$host+"\r\n") $err:=TCP_Send ($socket;"Content-Length: "+String($length)+"\r\n") $err:=TCP_Send ($socket;"Content-Type: multipart/form-data; boundary=-"+$boundary+"\r\n") $err:=TCP_Send ($socket;"\r\n") $err:=TCP_Send ($socket;$beforeContent) $err:=TCP_SendBLOB ($socket;$content) $err:=TCP_Send ($socket;$afterContent) `レスポンス受信 Repeat SET BLOB SIZE($buffer;0) $err:=TCP_ReceiveBLOB ($socket;$buffer) $err:=TCP_State ($socket;$status) $bufferLen:=BLOB size($buffer) $dataLen:=BLOB size($data) INSERT IN BLOB($data;$dataLen;$bufferLen) COPY BLOB($buffer;$data;0;$dataLen;$bufferLen) Until (($status=0) | ($err#0)) $err:=TCP_State ($socket;$state) $err:=TCP_Close ($socket) `ヘッダの除去 $text:=BLOB to text($data;Mac C string ) $pos:=Position("\r\n\r\n";$text) DELETE FROM BLOB($data;0;$pos+3) `先頭から最初の空行までの間を除去する `ファイルの出力 $doc:=Create document($resultFile) CLOSE DOCUMENT($doc) BLOB TO DOCUMENT($resultFile;$data)
以下の例では http://print.cssj.jp/ をPDF化します。 パラメータの input.include 画像等の取得のためにアクセスを許可するアドレスのパターンです。
C_TEXT($host;$user;$password;$include;$uri;$query;$resultFile;$text) C_LONGINT($port;$err;$status;$socket;$pos) C_BLOB($content;$buffer;$data) C_TIME($doc) `Copper PDFサーバー $host:="neko" $port:=8097 $user:="user" $password:="localhost" `変換対象アドレス $include:="hhttps://copper-pdf.com/**" $uri:="https://copper-pdf.com/" `結果ファイル名 $resultFile:="Result.pdf" `通信開始 $err:=TCP_Open ($host;$port;$socket) $err:=TCP_State ($socket;$status) `リクエスト送信 $query:="rest.user="+$user+"&rest.password="+$password+ "&input.include="+$include+"&rest.mainURI="+$uri $err:=TCP_Send ($socket;"GET /transcode?"+$query+" HTTP/1.0\r\n") `keep-aliveとchunkedを使わないためHTTP/1.0で接続する $err:=TCP_Send ($socket;"Host: "+$host+"\r\n") $err:=TCP_Send ($socket;"\r\n") $err:=TCP_Send ($socket;$beforeContent) $err:=TCP_SendBLOB ($socket;$content) $err:=TCP_Send ($socket;$afterContent) `レスポンス受信 Repeat SET BLOB SIZE($buffer;0) $err:=TCP_ReceiveBLOB ($socket;$buffer) $err:=TCP_State ($socket;$status) $bufferLen:=BLOB size($buffer) $dataLen:=BLOB size($data) INSERT IN BLOB($data;$dataLen;$bufferLen) COPY BLOB($buffer;$data;0;$dataLen;$bufferLen) Until (($status=0) | ($err#0)) $err:=TCP_State ($socket;$state) $err:=TCP_Close ($socket) `ヘッダの除去 $text:=BLOB to text($data;Mac C string ) $pos:=Position("\r\n\r\n";$text) DELETE FROM BLOB($data;0;$pos+3) `先頭から最初の空行までの間を除去する `ファイルの出力 $doc:=Create document($resultFile) CLOSE DOCUMENT($doc) BLOB TO DOCUMENT($resultFile;$data)
HTTP/RESTインターフェースは、さらに多くの種類の開発環境から、様々な方法で利用することできます。 最新情報はCopper PDFのサイト(https://copper-pdf.com/)で提供しています。