これからSDKで開発する人や既に開発している人のために、
SDKでどんなことができるのか、サンプルを紹介していきます。

ASP.NETの知識があれば、FullWEB SDKの知識ゼロでも読み進められます。
(以下のサンプルコードはVisual Basicで書いています)

第5回 承認後の自動配信
第6回 他システム連携(WEBアプリケーション) < 11月更新

第5回 承認後の自動配信

FullWEBには承認フロー機能が標準で搭載されています。
FullWEBで承認が完了した直後に、関連するいくつかの処理を続けて行いたいことがあります。例えば業務連絡書のようなファイルを承認フローに回して最終承認者の承認が完了したら関係者に自動配信するというのはよくある業務シナリオの1つです。

例えばWORDで業務連絡書のファイルを作成し、分類フォルダ「業務連絡書」に登録します。

FullWEBの属性編集画面を起動して表題と配信先を設定しておきます。

承認依頼を出して上長の承認が完了したら、配信先に設定した部署の各ユーザにメール送信されていくという流れです。
以下は送信されたメール本文の例です。

今回はSDKを用いて、承認が完了した後に電子メールで関係者に配信する例を紹介します。


FullWEBでの設定

まず業務連絡書の分類ラベルを定義しておきます。表題と配信先の2つ属性項目を作っておきます。表題は配信メールのSubject、配信先は総務部や生産部など配信先の部署を想定しています。部署はFullWEBのユーザーグループとして作成されているとします。
複数配信先があるのを想定して多値入力の設定をチェックONにしておきます。こうすることによって、1つの属性項目にスペース区切りで複数の値を設定することができるようになります。

SDKで開発する内容

承認完了のイベントを待ち受けて、承認済になった業務連絡書ファイルから表題と配信先の属性値を取得します。それから配信先のユーザーグループに所属するユーザに対して電子メールを次々と送付します。

最初にVisual Studio で開発環境を整えます。
(FullWEB SDKマニュアルに掲載しています)

今回はVisual StudioでCnEventHandlerというクラスを追加してそこにコードを追加することにします。

このクラスにcnWebCoreTest.IWebCoreHandlerというインターフェースをImplementsするようにします。

Public Class CnEventHandler
    Implements cnWebCoreTest.IWebCoreEvent

    Public ReadOnly Property IsSupported(command As String) As Boolean 
        Implements cnWebCoreTest.IFileFilter.IsSupported
        Get
        End Get
    End Property
    Public Function Filter(f As cnWebCoreTest.File, xParam As String) As String 
        Implements cnWebCoreTest.IFileFilter.Filter

    End Function
    Public Function InitInstance(db As cnWebCoreTest.Database) As Boolean 
        Implements cnWebCoreTest.IFileFilter.InitInstance

    End Function
    Public Sub TerminateInstance() Implements cnWebCoreTest.IFileFilter.TerminateInstance
    End Sub
End Class

IsSupported()がどのイベントを受け取るかを決めるプロパティです。各イベント発生時に呼び出され、Trueを返した場合に後述のFilter()メソッドが呼び出されます。

Filter()が各種イベント発生したときに呼ばれるメソッドです。

InitInstance()がこのクラスが初期化された時に呼ばれるメソッドです。(通常ログインした時です)
Databaseオブジェクトが渡ってきます。
※DatabaseオブジェクトはFullWEBの情報を取得するのに必要なオブジェクト

TerminateInstance()が解放時に呼ばれるメソッドです。(通常ログアウトした時です)
特別な処理がなければ、中身は空のままでも構いません。

準備したCnEventHandlerクラスをFullWEBのweb.configに以下のように設定してFullWEBに登録しておきます。
nameはdllファイル名、typeはクラス名を指定します。

    <webCoreEvent>
      <add name="WebApplication1.dll" type="CnWebApplication1.CnEventHandler" />
    </webCoreEvent>

こうすることによって、ユーザがFullWEBで承認作業を行ったときにCnEventHandlerクラスの各メソッドが自動的に呼び出されます。

これで準備ができましたので、実装していきます。
まずInitInsntance()を実装して、初期化された時にDatabaseオブジェクトを保持するようにします。

    Private m_db As cnWebCoreTest.Database

    ''' <summary>
    ''' 初期化処理
    ''' </summary>
    Public Function InitInstance(db As Database) As Boolean Implements IFileFilter.InitInstance
 
        m_db = db
        Return True
    End Function

IsSupported()を実装して承認完了イベントを受け取ることができるようにします。
引数にはイベント名が渡ってきます。”AfterApprove”が承認完了時のイベント名です。

    ''' <summary>
    ''' 各イベントを受け取るかどうかを返す
    ''' </summary>
    ''' <param name="command">各種イベント名</param>
    ''' <returns></returns>
    Public ReadOnly Property IsSupported(command As String) As Boolean Implements IFileFilter.IsSupported
        Get
            Select Case command.ToLower
                Case "afterapprove"
                    '   承認完了イベントを受け取る
                    Return True
                Case Else
                    '   それ以外は受け取らない
                    Return False
            End Select
        End Get
    End Property

Filter()を実装して、承認完了時の処理を書きます。
AfterApproveイベントが発生した時に後述のAfterApprove()メソッドを呼び出しています。

この時渡されるパラメータは各種承認情報が入っているXMLです。

    Public Function Filter(f As File, xParam As String) As String Implements IFileFilter.Filter
        Dim xp As XElement = XElement.Parse(xParam)
        Select Case xp.@command.ToLower
            Case "afterapprove"
                Return AfterApprove(xp)
            Case Else
                Return False
        End Select
    End Function

    Private Function AfterApprove(ByVal xp As XElement) As String
	・・・
    End Function

XMLの中には1つのファイルに対する承認依頼をユニークに区別するsdidという値が入っています。そこから承認されたファイルをユニークに区別するfidを取得します。
AfterApproveイベントでは最終承認完了だけでなく、差し戻し、承認完了(次の承認者へ)のタイミングでも発生します。XMLの中にはその種類が分かる文字列が入っているので、最終承認完了の時だけ後述のDistributeFile()メソッドを呼び出すようにします。

   Private Function AfterApprove(ByVal xp As XElement) As String
        For Each xt In xp.<ApprovalParam>.<Target>
            '   対象ファイルを取得
            Dim sdid As Integer = CInt(xt.@sdid)
            Dim fid As Integer = m_db.DbHelper.GetFidBySdid(sdid)
            '-- 承認処理
            Select Case (xt.@result)
                Case "done"
                    '   承認完了。配信処理へ
                    DistributeFile(fid)
                Case "continue"
                    '   承認(次の人へ)
                Case "rejected"
                    '   差し戻し
                Case Else
                    '   
            End Select
        Next
        Return xp.<ApprovalParam>(0).ToString
    End Function

    Private Sub DistributeFile(ByVal fid As Integer)
	・・・
    End Sub

DistributeFile()メソッドの中では、承認完了したファイルから表題と配信先の属性値を取得します。
配信先は部署で、FullWEBではユーザーグループとして扱う前提ですので、ユーザーグループ一覧の情報を取得して、所属ユーザのメールアドレス一覧を得ます。

最後に.NETの標準機能を使ってメール送信していけば処理完了です。

     Private Sub DistributeFile(ByVal fid As Integer)
        '   Fileオブジェクトの取得
        Dim f As cnWebCoreTest.File = m_db.GetFile(fid)
        If f.ContainsAttr("業務連絡書") Then
            '   業務連絡書ファイルではないので何もしない
            Return
        End If
        '   表題属性取得
        Dim alidTitle As Integer = m_db.GetALID("業務連絡書", "表題")
        Dim title As String = f.Attrs("業務連絡書").Item("k" & alidTitle.ToString).Value
        '   配信先属性取得
        Dim alidDist As Integer = m_db.GetALID("業務連絡書", "配信先")
        Dim distVal As String = f.Attrs("業務連絡書").Item("k" & alidDist.ToString).Value
        '   ユーザーグループの情報を取得する
        Dim dicUg As New Dictionary(Of String, Integer)
        Dim uglistXml As String = m_db.DbHelper.GetUserGroupsAll()
        Dim xUgList As XElement = XElement.Parse(uglistXml)
        For Each xUg As XElement In xUgList.<ug>
            If dicUg.ContainsKey(xUg.<value>.Value) = False Then
                dicUg.Add(xUg.<value>.Value, CInt(xUg.<id>.Value))
            End If
        Next
        '   メールアドレス一覧を取得する
        Dim emailAddressList As New List(Of String)
        For Each dist As String In distVal.Split(" "c) 
            If dicUg.ContainsKey(dist) = False Then
                '   配信先に設定された値がユーザーグループでない
                Continue For
            End If
            Dim emlist As List(Of String) = GetMailAddressList(dicUg.Item(dist))
            emailAddressList.AddRange(emlist.ToArray)
        Next
        SendMail(f, title, emailAddressList) '   .NET標準機能でメール送信
    End Sub

以下はユーザーグループ(部署)に所属するユーザ―のメールアドレス一覧を取得するメソッドです。
DistributeFile()メソッドから呼び出されています。

    ''' <param name="ugid">ユーザーグループを特定するugid</param>
    Private Function GetMailAddressList(ByVal ugid As Integer) As List(Of String)
        Dim ret As New List(Of String)
        Dim users As New Users(ugid, m_db)
        For i As Integer = 1 To users.Count
            Dim email As String = users.Item(i).eMail(0)
            If String.IsNullOrEmpty(email) = False Then ret.Add(email)
        Next
        Return ret
    End Function

DistributeFile()メソッドの最後にSendMail()という関数を呼び出していますが、.NET標準機能を使ってメール送信処理を実装していけば良いため、詳細は記述していません。

※メール本文に
https://hostname/FullWEB/File.aspx?fid=〇〇
というURLを入れておけば、メールを受け取ったユーザはこのリンクをクリックするだけで配信された業務連絡書の属性画面を直接起動することができるので便利です。

これで実装は完了です。
このようにFullWEBの機能とSDKを組み合わせることで、実現したいシナリオを柔軟に対処できます。

第6回 他システム連携(WEBアプリケーション)

第2, 3回でEXE形式の自動登録ツールを作成しました。
この自動登録ツールを使うと、他システムからは指定フォルダへファイルを配置するだけで自動でファイルが登録されます。
今回は他システムと連携するWEBアプリケーションを作成します。
これはFullWEB WEBアプリケーションとは別のWEBアプリケーションです。
下図の「独自WEBアプリケーション」の位置づけになります。

画像:独自WEBアプリケーションの位置づけ説明

Visual StudioでASP.NET Webアプリケーションプロジェクトを新規作成し、FullWEB SDKのモジュールを参照に追加します。(詳細はFullWEB SDKマニュアルに掲載しています)
今回作成するプログラムでは、ファイル番号を受け付けたら、該当する実ファイルデータをBASE64エンコードした文字列を返します。ただし、[公開設定]ラベルの[公開]属性項目(チェック型)がONになっているものを対象とします。
レスポンスデータは、BASE64エンコードした実ファイルデータを含むJSON文字列とします。
この機能を担当するaspxページをプロジェクトに追加します。
GetPublicFile.aspx という名前にしましょう。

GetPublicFile.aspxは、リクエストを受け付けたら、指定のユーザ/パスワードでログインします。
そして、リクエストパラメータのファイル番号からFileオブジェクトを取得し、[公開設定]ラベルの[公開]属性項目の値を調べます。
ここまでの流れは第1回から第3回で説明済みです。
コードは以下のようになります。

Const server As String = "localhost"                  ' 接続先
Const user As String = "admin"                        ' ユーザ名
Const password As String = ""                         ' パスワード

Dim lm As cnWebCoreTest.LoginManager = Nothing

Try
    ' リクエストからファイル番号を取得
    Dim fid = CInt(Request.Params("fid"))

    ' ログイン情報
    Dim xParam As XElement = <param
                                    mode="new"
                                    lcuser=<%= user %>
                                    lctime=<%= Now.ToString("yyyyMMddHHmmss") %>
                                    atime=<%= Now.ToString("yyyyMMddHHmmss") %>
                                    pc=""
                                    ipaddr=""
                                    datakey=""/>
    lm = cnWebCoreTest.LoginManager.CreateInstance(server, xParam)
    ' ログイン
    Dim err As String = lm.Connect(lm.UserName, password, True)

    If err <> "" Then
        ' ログインエラーなら終了
    End If

    Dim db As cnWebCoreTest.Database = lm.Database

    ' Fileオブジェクト取得
    Dim f As cnWebCoreTest.File = db.SafeGetFile(resData.fid)
    If f Is Nothing Then
        ' Fileオブジェクトが取得できなければ終了
    End If

    ' 属性値の確認
    If f.ContainsAttr("公開設定") = False Then
        ' 公開設定ラベルが付与されていなければ終了
    End If

    Dim alid As Integer = db.GetALID("公開設定", "公開")
    Dim alVal As String = f.Attrs("公開設定").Item("k" & alid.ToString).Value

    If alVal <> "1" Then
        ' 公開チェックボックスの値がONでなければ終了
    End If

Catch ex As Exception
    ' エラー
Finally
    ' 必ずログアウト
    If lm IsNot Nothing Then
        lm.Disconnect()
    End If
End Try

次は実ファイルを取得する処理です。
FileオブジェクトのCopy()メソッドを使います。
第一パラメータは、取り出し先フォルダのパス、第二パラメータは取り出し先に保存するファイル名です。
この取り出し先は独自WEBアプリケーションが動いているサーバのフォルダです。
マルチリクエストに対応できるように、ファイル名にはGUIDなどの重複しないファイル名を付ける必要があります。

' ファイルを一時フォルダに取り出す
Dim serverPath As String = "C:¥DAV"
Dim fileName As String = Guid.NewGuid.ToString & f.Extension
f.Copy(serverPath, fileName)

残りの作業は、ファイルデータをBASE64エンコードすることとJSON形式のレスポンスを返すことです。
これらは.NETのAPIでの実装になります。
BASE64エンコード文字列だけではなく、リクエストで受け付けたファイル番号、エラーがあった場合はエラーコードとエラーメッセージも返すようにしましょう。
コード全体は以下のようになります。
※server、user、password 変数の値はWeb.configから取得しています。
passwordは暗号化しています。Decryption() メソッドは適宜コーディングしてください。

■Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="server" value="localhost"/>
    <add key="user" value="admin"/>
    <add key="password" value="aG9nZSANCg0K"/>
  </appSettings>
  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp"  />
      <compiler language="vb;vbs;visualbasic;vbscript" />
    </compilers>
  </system.codedom>
</configuration>

■GetPublicFile.aspx.vb

Private Structure ResponseData
    Property fid As Integer
    Property errorCode As Integer
    Property errorMessage As String
    Property fileName As String
    Property fileData As String
End Structure
			
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim resData As New ResponseData()
    Dim lm As cnWebCoreTest.LoginManager = Nothing
    Dim server As String = ConfigurationManager.AppSettings("server")    ' 接続先
    Dim user As String = ConfigurationManager.AppSettings("user")         ' ユーザ名
    Dim password As String = Decryption(ConfigurationManager.AppSettings("password"))    ' パスワード
			
    Try			
        ' リクエストからファイル番号を取得
        resData.fid = CInt(Request.Params("fid"))
			
        ' ログイン情報
        Dim xParam As XElement = <param
                                        mode="new"
                                        lcuser=<%= user %>
                                        lctime=<%= Now.ToString("yyyyMMddHHmmss") %>
                                        atime=<%= Now.ToString("yyyyMMddHHmmss") %>
                                        pc=""
                                        ipaddr=""
                                        datakey=""/>
        lm = cnWebCoreTest.LoginManager.CreateInstance(server, xParam)
        ' ログイン
        Dim err As String = lm.Connect(lm.UserName, password, True)
	
        If err <> "" Then
            ' ログインエラーなら終了
            With resData
                .errorCode = 1
                .errorMessage = err
            End With
            Exit Try
        End If
	
        Dim db As cnWebCoreTest.Database = lm.Database
	
        ' Fileオブジェクト取得
        Dim f As cnWebCoreTest.File = db.SafeGetFile(resData.fid)
        If f Is Nothing Then
            With resData
                .errorCode = 1
                .errorMessage = "ファイルが見つからない"
            End With
            Exit Try
        End If
	
        ' 属性値の確認
        If f.ContainsAttr("公開設定") = False Then
            With resData
                .errorCode = 1
                .errorMessage = "非公開ファイル"
            End With
            Exit Try
        End If
	
        Dim alid As Integer = db.GetALID("公開設定", "公開")
        Dim alVal As String = f.Attrs("公開設定").Item("k" & alid.ToString).Value

        If alVal <> "1" Then
            With resData
                .errorCode = 1
                .errorMessage = "非公開ファイル"
            End With
            Exit Try
        End If

        ' ファイルを一時フォルダに取り出す
        Dim serverPath As String = "C:¥DAV"
        Dim fileName As String = Guid.NewGuid.ToString & f.Extension
        f.Copy(serverPath, fileName)

        Dim workPath As String = IO.Path.Combine(serverPath, fileName)
			
        ' Base64文字列に変換
        Dim byteStream() As Byte = Nothing
        Dim base64str As String = ""
        Try
            Using fs As New IO.FileStream(workPath, IO.FileMode.Open, IO.FileAccess.Read)
                ReDim byteStream(fs.Length - 1)
                Dim readBytes As Long = fs.Read(byteStream, 0, fs.Length)
                fs.Close()
            End Using
            base64str = Convert.ToBase64String(byteStream)
        Finally
            ' 一時フォルダのファイルを削除
            If IO.File.Exists(workPath) Then
                IO.File.Delete(workPath)
            End If
        End Try
			
        resData.fileData = base64str
        resData.fileName = f.Name
    Catch ex As Exception
        With resData
            .errorCode = ex.HResult
            .errorMessage = ex.Message
        End With	
    Finally
        ' 必ずログアウト
        If lm IsNot Nothing Then
            lm.Disconnect()
        End If
    End Try
			
    ' JSON文字列を返す
    Response.ContentType = "application/json"
    Response.AddHeader("Access-Control-Allow-Origin", "*")    ' CORSを許可
    Response.AddHeader("Access-Control-Allow-Headers", "Origin, X - Requested -With, Content - Type, Accept")    ' CORSを許可
    Response.Clear()
    Response.Write(New JavaScriptSerializer().Serialize(resData))
    Response.Flush()
    Response.End()
End Sub
			
Private Function Decryption(s As String) As String
    ' 適宜、復号化を実施します。	
    Return s
End Function

完成したWEBアプリケーションをIISに登録したら、実際にアクセスしてみます。

以下のようなテストページを作って表示します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>テストページ</title>
    <script type="text/javascript">
        function cnsdkExec() {
            var fid = document.getElementById('fid').value;
            var httpRequest = new XMLHttpRequest();
            if (!httpRequest) {
                return;
            }
            httpRequest.onreadystatechange = function () {
                if (httpRequest.readyState === XMLHttpRequest.DONE) {
                    if (httpRequest.status === 200) {
                        if (httpRequest.response.errorCode == 0) {
                            var a = document.createElement("a");
                            a.href = "data:application/octet-stream;base64," + httpRequest.response.fileData;
                            a.download = httpRequest.response.fileName;
                            a.click();
                        }
                    } else {
                        alert('リクエストに問題が発生しました');
                    }
                }
            }
            httpRequest.responseType = "json";
            httpRequest.open('Get', 'http://piglet/cmd211102/GetPublicFile.aspx/?fid=' + fid);
            httpRequest.send();
        }
    </script>
</head>
<body>
    <form action="GetPublicFile.aspx" method="post">
        <input id="fid" type="text" value="51393394" />
        <input type="button" value="Get File" onclick="cnsdkExec();" />
    </form>
</body>
</html>

ボタンをクリックするとファイルがダウンロードされます。

画像:ファイルダウンロード

< SDKでできること~初級編~