DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 9 回です。
今回はイメージリソース(設計要素) から 画像を取り出す方法についてまとめます。
画像ファイルの状態
まず、前回確認したイメージリソースの DXL で画像データは次のように文字列で表されていました。
画像データであるバイナリーデータが Base64 でエンコードした状態となっています。メールの添付ファイル(MIME)と同様ですね。
Base64 のデコード
エンコードされた画像ファイル(=文字列)を Base64 でデコードすれば、画像データが取得できます。では、どうやってデコードするのでしょうか?
私が DXL に出会うきっかけとなった OpenNTF の LotusScript Gold Collection プロジェクトで公開されている DB 内で関数化されていました。今回はこれを拝借します。
私が作ったコードではないので、関数全体をコメント付きでそのまま転載します。
%REM Sub Base64ToBinary Description: Given a string of base64-encoded data, write into a binary stream we are passed. This is done rather than creating the stream here and returning it, so that you can stream directly into a file if you choose. %END REM Sub Base64ToBinary(strBase64$, streamOut As NotesStream) ' Given a string of base64 encoded data, this routine decodes and writes the original binary data into a NotesStream Dim doc As NotesDocument Dim mime As NotesMIMEEntity Dim streamIn As NotesStream Dim db As NotesDatabase Dim session As New NotesSession Set db = session.CurrentDatabase Set doc = db.CreateDocument Set mime = doc.CreateMIMEEntity("Body") ' the mime classes already know how to do this conversion, Set streamIn = session.CreateStream Call streamIn.WriteText(strBase64) streamIn.Position = 0 Call mime.SetContentFromText(streamIn, "binary", ENC_BASE64) Call mime.GetContentAsBytes(streamOut, True) ' decode as you stream out the data. End Sub |
デコードは NotesMIMEEntity クラスを活用して実行しているようです。このクラスは、今回初めて利用したので詳細はわかりかねるのですが、SetContentFromText メソッドで、エンコード文字列をデコードしつつ NotesMIMEEntity のオブジェクトに取り込み、GetContentAsBytes メソッドでバイナリデータとして抽出しているようです。
サンプルプログラム
それでは、上記関数も活用しつつ、イメージリソースからファイルを抽出するプログラムを作成します。
まず、メインルーチンです。前回のコードの DXL を保存する部分を画像ファイルをダウンロードする新しい関数を指定しています。
Option Declare Private xns As NotesSession Sub Initialize Dim ndb As NotesDatabase Dim ndAgent As NotesDocument Set xns = New NotesSession Set ndb = xns.CurrentDatabase Dim nnc As NotesNoteCollection Set nnc = ndb.CreateNoteCollection(False) nnc.SelectImageResources = True nnc.SelectionFormula = xGetFormula("TitleS.PNG") Call nnc.BuildCollection() Dim dprs As NotesDOMParser If nnc.Count > 0 Then Set ndAgent = ndb.GetDocumentByID(nnc.GetFirstNoteID) Set dprs = xGetDOMParser(ndAgent) Call xDownloadImage(dprs, "d:\denaoshi.png") End If End Sub |
続いて、画像ファイルをダウンロードするメインルーチンです。まず、png エレメントノードを取得して、Base64 でエンコードされた画像データを sB64 変数に代入しています(赤字)。png ノードの直下にエンコード文字列があります。この場合、最初の子ノードがテキストノードとなるため、このようはコードになっています。
Function xDownloadImage(vdprs As NotesDOMParser, ByVal vsFP As String) As Boolean 'DOM ツリーのルートを取得 Dim ddn As NotesDOMDocumentNode Set ddn = vdprs.Document 'ImageResource エレメントの取得 Dim denImage As NotesDOMElementNode Set denImage = ddn.DocumentElement '画像ファイルダウンロード Dim denPNG As NotesDOMElementNode Dim dnl As NotesDOMNodeList Dim dtn As NotesDOMTextNode Dim nst As NotesStream Dim sB64 As String Set dnl = denImage.GetElementsByTagName("png") If dnl.NumberOfEntries > 0 Then Set denPNG = dnl.GetItem(1) Set dtn = denPNG.FirstChild 'エンコードされた画像データ取得 sB64 = dtn.NodeValue 'ファイルとして保存 Set nst = xns.CreateStream() Call Base64ToBinary(sB64, nst) Call StreamToImageFile(nst, vsFP) End If End Function |
取得したエンコード文字列をファイルに変換しているのは青字の部分です。事前に紹介した関数を使用して、エンコード文字列をバイナリデータに変換し、NotesStream にセットしています。それを ファイルに出力する関数 StreamToImageFile に渡しています。
StreamToImageFile 関数は次の通りです。ファイルを NotesStream で開いて、イメージデータの NotesStream から ファイルの NotesStream に渡しています。
Sub StreamToImageFile(vnstImage As NotesStream, ByVal vsFP As String) Dim nstOut As NotesStream On Error Resume Next Kill vsFP '存在してたら削除 Set nstOut = xns.CreateStream() Call nstOut.Open(vsFP) vnstImage.Position = 0 Do Until vnstImage.Position >= vnstImage.Bytes Call nstOut.Write(vnstImage.Read(16000)) Loop End Sub |
NotesStream クラスの使い方ってなんとなく抽象的で、つかみどころがなく苦手です。
ファイルみたいなもので、Position を使って、ファイル内を行ったり来たりできるということなのでしょうね。このコードを書いていてそんな気がしてきました。
実行結果とまとめ
このプログラムを実行すると次のように画像ファイルが出力されます。
ノーツでノーツアプリを作っているだけでは、ノーツ以外の知識以外が身に付きにくいですよね。今回初めて Base64 について調べることになりました。DXL は、LotusScript でノーツアプリを作っているだけではあるのですが、少しだけ外の世界を見るきっかけとなりました...
前回 | DXL Step-by-Step | 次回 |
0 件のコメント:
コメントを投稿