DXL 経由で添付ファイルのダウンロードに関して、前回 は、プログラムの全体像を説明しました。今回はその続きです。添付ファイルの実体をを取得する部分を紹介します。
呼び出し元の確認
まずは、呼び出し元のプログラムを再確認します。
attachmentref ノードが denRef にセットされており、name 属性から文書内で一意となるファイル名を取得しています。このファイル名を引数に、そのファイルの実体を保存している $FILE フィールドを取得する関数が xGetDXL_FileItem でした。
If Not (denRef Is Nothing) Then 'ファイル名取得 Dim sName As String Dim sDisp As String sName = denRef.GetAttribute("name") sDisp = denRef.GetAttribute("displayname") '$FILE フィールド取得 Dim denFile As NotesDOMElementNode Set denFile = xGetDXL_FileItem(ddn, sName) 'Notes 内部の名称で検索 |
添付ファイルの DXL 確認
続いて、添付ファイルの DXL 構造の再確認です。
添付ファイルは $FILE というフィールド内に保存されいました。下図 の赤線のように $FILE も通常のフィールドと同列なので、Title や Body といったフィールド(item ノード)に並んで登場します。
item ノード内に添付ファイルがある場合、item > object > file と階層化さた file ノードの name 属性に、一意となるファイル名がセットされています。
よって、添付ファイルの実体を探す際には、item ノードだけでなく、file ノードの属性を含めて判定する必要があります。
これで作成すべきロジックが見えてきましたね。
ファイルの実体の取得
では、添付ファイルの実体を取得する関数 xGetDXL_FileItem を紹介します。
フィールドを取得する関数 xGetDXL_item をベースに作成しました。通常のフィールドと違うのは、フィールド名が $FILE 固定になっている点です(赤字)。フィールド名が $FILE であれば、file ノードを取得して、ファイル名を判定しています(紫字)。
Function xGetDXL_FileItem(vddn As NotesDOMDocumentNode, ByVal vsName As String) As NotesDOMElementNode '文書のノードの取得 Dim denDoc As NotesDOMElementNode Set denDoc = vddn.DocumentElement 'itemノードをチェック Dim denItem As NotesDOMElementNode Dim dnl As NotesDOMNodeList Dim i As Integer Dim sFld As String Dim sName As String Dim den As NotesDOMElementNode Set dnl = denDoc.GetElementsByTagName("item") For i = 1 To dnl.NumberOfEntries Set denItem = dnl.GetItem(i) sFld = denItem.GetAttribute("name") If LCase(sFld) = LCase("$FILE") Then '添付ファイルなのでチェックを継続 'object ノード取得 Set den = xGetDXL_FirstNodeByName(denItem, "object") If Not (den Is Nothing) Then 'file ノード取得 Set den = xGetDXL_FirstNodeByName(den, "file") If Not (den Is Nothing) Then '添付ファイルなので Notes 内部のファイル名取得 sName = den.GetAttribute("name") If LCase(sName) = LCase(vsName) Then 'ファイル名一致 '戻り値セットしてループ脱出 Set xGetDXL_FileItem = den 'file ノード Exit For End If End If End If End If Next End Function |
object や file ノードの取得は ”最初の子ノード” というような単純な取得ではなく、xGetDXL_FirstNodeByName 関数を利用して検索しています。また、ノードが見つからないときは、次のフィールドに進むようになっています。
$FILE フィールドは、添付ファイル以外にも利用されるようなので、それに備えています。
メインプログラム
これで必要な関数がそろいました。エージェントの本体、Initialize の処理を修正します。
作成した xGetDXL_FirstAttachment 関数をコールして Body フィールド内の最初の添付ファイルを取得します。戻り値は、添付ファイル名です。
Sub Initialize Dim ndb As NotesDatabase Dim ndc As NotesDocumentCollection Dim nd As NotesDocument '処理対象の文書を取得 Set xns = New NotesSession Set ndb = xns.CurrentDatabase Set ndc = ndb.UnprocessedDocuments Set nd = ndc.GetFirstDocument() '画像データの取得 Dim nst As NotesStream '添付ファイル Dim sName As String 'ファイル名 If Not(nd Is Nothing) Then 'フィールドの内の最初の添付を取得 sName = xGetDXL_FirstAttachment(nd, "Body", nst) If sName <> "" Then '取得できたらファイルとして保存 Call StreamToFile(nst, "c:\tmp\" & sName) End If End If End Sub |
添付ファイルが取得できたら(= sName に値がある)、保存処理を行います。nst にファイルの中身が NotesStream オブジェクトとして入っているので、StreamToFile 関数で保存します。
Sub StreamToFile(vnst As NotesStream, ByVal vsFP As String) Dim nstOut As NotesStream On Error Resume Next Kill vsFP '存在してたら削除 Set nstOut = xns.CreateStream() Call nstOut.Open(vsFP) vnst.Position = 0 Do Until vnst.Position >= vnst.Bytes Call nstOut.Write(vnst.Read(16000)) Loop End Sub |
この関数、どこかで見たことがありますね。
#9 で作成し、今回もとにしたエージェント #42 でも利用したダウンロードした画像をファイルとして保存する StreamToImageFile 関数です。今回は画像ではないので "Image" とった名前にしています。
関数の機能としては、画像に特化していません。初期段階で命名を失敗したということですね...
前回 | DXL Step-by-Step |
0 件のコメント:
コメントを投稿