2017年2月26日日曜日

オブジェクトのトランスレーション+VB.net

ビューア用に変換

バケットにアップロードしたオブジェクトを、ビューア用のデータであるSVF形式に変換します。使用するAPIは「Model Derivative API」の「POST job」です。

シナリオ

前回までのバケットの選択→オブジェクトIDの取得 の流れを利用して、オブジェクトを変換してみます。バケットを選択しオブジェクト一覧を表示するGridViewに「SVF変換」の列を設けて、選択したオブジェクトをSVFに変換します。
SVF変換

使用するAPI

アップロードしたオブジェクトの変換には、「Model Derivative API」の「POST job」を使います。

URI

https://developer.api.autodesk.com/modelderivative/v2/designdata/job

アクセストークン

変換には「data:read」と「data:write または data:create」でアクセストークンを取得します。data:createを使うと、同じオブジェクトでも上書きされず、次々新しい変換ができますので、今回は data:read data:write を使います。

リクエストボディ~JSON

こんかいちょっとややこしいのは、送信するボディにJSONを使用することです。このJSONの形式は以下の通りです。
{
   "input": {
     "urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bW9kZWxkZXJpdmF0aXZlL0E1LnppcA",
     "compressedUrn": true,
     "rootFilename": "A5.iam"
   },
   "output": {
     "formats": [
       {
         "type": "svf",
         "views": [
           "2d",
           "3d"
         ]
       }
     ]
   }
 }
これを単に文字列を使って作成してもいいのですが、クラスとしてこのJSONを表現し、Newtonsoft.Json.JsonConvert.SerializeObjectを使ってJSON文字列にしてみましょう。まず、このJSONをクラスに置き換える方法ですが、こちらに大変便利なWebサイトがあります。こちらではJSONとC#クラスの変換を助けてくれます。上記JSONを貼り付けてGenerateボタンを押すと
public class Input
{
    public string urn { get; set; }
    public bool compressedUrn { get; set; }
    public string rootFilename { get; set; }
}

public class Format
{
    public string type { get; set; }
    public List<string> views { get; set; }
}

public class Output
{
    public List<Format> formats { get; set; }
}

public class RootObject
{
    public Input input { get; set; }
    public Output output { get; set; }
}
となり、クラスが4つ作成されました。VB.netでこのクラスを定義すると

Public Class Input
    Public urn As String
End Class

Public Class Format
    Public type As String
    Public views As List(Of String)
End Class

Public Class Output
    Public formats As List(Of Format)
End Class

Public Class RootObject
    Public input As Input
    Public output As Output
End Class

となります。これをプロジェクト内に定義して [RootObject]クラスを生成し、JSONにコンバートすれば、JSON文字列を生成できます。

バケットの内容一覧

バケットの内容一覧を表示する部分は、前回を参照してください。

SVF変換用ButtonField

WebFormをもう一つ追加して、下の図のように設定します。
Webフォーム
SVF変換用のButtonFieldをGridViewに付け加えます。
ButtonFieldを付けくわて、ButtonStyleをButtonにする
このボタンフィールドのハンドラにSVF変換のコードを記入します。

コードサンプル

    Protected Sub gdvObjects_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles gdvObjects.RowCommand

        '何行目がクリックされたのか?
        Dim index As Integer = Convert.ToInt32(e.CommandArgument)
        Dim row As GridViewRow = gdvObjects.Rows(index)

        'オブジェクトIDの取得
        Dim objKey As String = row.Cells(1).Text
        Dim objId As String = row.Cells(2).Text

        '*******************************************
        '     アクセストークンを取得
        '*******************************************

        Dim acToken As String = mdlUtils.GetToken("data:write data:read")
        If acToken = "" Then
            lblBucketkey.Text = "アクセストークンの取得に失敗しました。"
            Exit Sub
        End If

        '*******************************************
        '     URN(ObjectId)をBase64エンコード
        '*******************************************

        Dim bytes As Byte() = System.Text.Encoding.UTF8.GetBytes(objId)
        Dim convURN As String = Convert.ToBase64String(bytes, Base64FormattingOptions.None)

        '*******************************************
        '     変換リクエスト(RestSharp)
        '*******************************************
        'クライアント
        Dim strClient As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(strClient)

        'リクエスト
        Dim transReq As New RestSharp.RestRequest()
        transReq.Resource = "modelderivative/v2/designdata/job"
        'メソッド
        transReq.Method = RestSharp.Method.POST
        'ヘッダー
        transReq.AddHeader("Authorization", "Bearer " + acToken)
        transReq.AddHeader("Content-Type", "application/json")
        'ボディのJSON文字列
        '{
        '   "input" {
        '               "urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bW9kZWxkZXJpdmF0aXZlL0E1LnppcA"
        '           },
        '   "output": {
        '               "formats": [
        '                            {
        '                              "type": "svf",
        '                              "views": ["2d","3d"]
        '                             }
        '                           ]
        '              }
        '}
        '送信するJSONをクラスで置き換えて作成
        Dim iInput As New Input
        iInput.urn = convURN

        Dim iFormat As New Format
        iFormat.type = "svf"
        iFormat.views = New List(Of String)
        iFormat.views.Add("2d")
        iFormat.views.Add("3d")

        Dim iOutput As New Output
        iOutput.formats = New List(Of Format)
        iOutput.formats.Add(iFormat)

        Dim iRootObj As New RootObject
        iRootObj.input = iInput
        iRootObj.output = iOutput

        'JSONオブジェクトに変換する
        Dim json As Object = Newtonsoft.Json.JsonConvert.SerializeObject(iRootObj)

        '変換したJSONオブジェクトをボディに追加する
        transReq.AddParameter("application/json", json, RestSharp.ParameterType.RequestBody)

        'リクエストを送信
        Dim result As RestSharp.IRestResponse = _client.Execute(transReq)

        '*******************************************
        '     応答
        '*******************************************
        If result.StatusCode = Net.HttpStatusCode.OK Then

            '200 成功した場合
            '戻り値のJSONは次の形式になっている
            '{
            '  "result": "success",
            '  "urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bW9kZWxkZXJpdmF0aXZlL0E1LnppcA",
            '  "acceptedJobs": {
            '    "output": {
            '      "formats": [
            '        {
            '          "type": "svf",
            '          "views": [
            '            "2d",
            '            "3d"
            '          ]
            '        }
            '      ]
            '    }
            '  }
            '}
            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            'URNを取得
            Dim strURN As String = jsonObj("urn")
            lblStatus.Text = "変換を開始しました。"
            tbxURN.Text = strURN

        ElseIf result.StatusCode = Net.HttpStatusCode.Created Then
            '201 すでに作成されている場合
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            Dim strURN As String = jsonObj("urn")
            lblStatus.Text = "すでに変換されています。"
            tbxURN.Text = strURN

        ElseIf result.StatusCode = Net.HttpStatusCode.BadRequest Then
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"diagnostic"の値にエラーの詳細が記載されている。
            Dim strDiagnostic As String = jsonObj("diagnostic")
            lblStatus.Text = "変換に失敗しました。" + strDiagnostic
            tbxURN.Text = ""

        Else
            '何らかの失敗
            lblStatus.Text = "変換に失敗しました。"
            tbxURN.Text = ""
        End If
    End Sub
End Class

'JSONクラス
Public Class Input
    Public urn As String
End Class

Public Class Format
    Public type As String
    Public views As List(Of String)
End Class

Public Class Output
    Public formats As List(Of Format)
End Class

Public Class RootObject
    Public input As Input
    Public output As Output
End Class

実行してみる

まず、バケットの一覧を表示します。
バケットの一覧
バケットを選択すると、

が表示されます。ここで[SVF変換]ボタンを押して、変換します。
変換が開始されるとURNが表示されます
時間をおいて、再度SVF変換を押すと「すでに変換されています」となります。

このURNを使って、ビューアにオブジェクトを表示することができます。


2017年2月4日土曜日

バケット内のオブジェクト+VB.net

バケット内のオブジェクト

作成したバケットにどのようなファイルがアップロードされているかを表示してみます。APIはData Management APIの「GET buckets/:bucketKey/objects」です。

リファレンスによると、必要な情報は

  • data:readのアクセストークン
  • バケットキー

の二つです。

(1) バケットの一覧を取得し表示
(2) 表示された一覧からバケットを選択
バケットの一覧を表示し「選択」をクリック
(3)バケット内のオブジェクトの一覧を表示
バケット内のオブジェクトを表示
というシナリオで構成してみます。
ASP.net Webフォームでこのお題を解いてみます。

バケットの一覧を取得してGridViewに表示する


前回はListViewにバケットの一覧を表示しましたが、今回はGridViewに表示します。新なWebフォームを追加して、GridView(gdvBucket)とラベル(lblStatus)を追加します。FORGE APIの部分は前回と同じですが、GridViewにデータを表示するために、新たにデータセット(DataSet)を作成して、GridViewにバインドします。どうもGridViewはデータベースと結びつけないと作動しないようです。


サンプルコード


Public Class WebForm4
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


        '**********************************
        '     アクセストークンを取得
        '**********************************

        Dim acToken As String = mdlUtils.GetToken("bucket:read")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     バケットを取得
        '**********************************

        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets"

            'メソッド
            .Method = RestSharp.Method.GET

            'ヘッダー
            .AddHeader("Authorization", "Bearer " + acToken)

        End With

        '送信
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = Net.HttpStatusCode.OK Then

            '200OKの場合


            'データセットを定義
            Dim dsBucket As New DataSet("BucketList")
            Dim tblBucket As DataTable = dsBucket.Tables.Add("Table1")
            tblBucket.Columns.Add("バケットキー", Type.GetType("System.String"))
            tblBucket.Columns.Add("作成日", Type.GetType("System.String"))
            tblBucket.Columns.Add("ポリシーキー", Type.GetType("System.String"))


            Dim responseString As String = result.Content

            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"items"を取得しjArrayオブジェクトとする
            Dim itemArray As Newtonsoft.Json.Linq.JArray = jsonObj("items")
            '配列を走査し、データテーブルにデータ行を充てんする
            For Each item As Newtonsoft.Json.Linq.JObject In itemArray
                'バケットキー
                Dim strBucketKey As String = item("bucketKey")
                '作成した日付(ミリセカンド)
                Dim strCreatedDate As String = item("createdDate")
                'ポリシーキー
                Dim strPolicyKey As String = item("policyKey")

                'タイムスタンプから日付へ変換
                Dim intTimeStamp As Int64 = Int64.Parse(strCreatedDate)
                Dim dtCreateDate As DateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(intTimeStamp)


                'データセット
                Dim rowBucket As DataRow = tblBucket.NewRow()
                rowBucket("バケットキー") = strBucketKey
                rowBucket("作成日") = dtCreateDate.ToLocalTime.ToString
                rowBucket("ポリシーキー") = strPolicyKey
                tblBucket.Rows.Add(rowBucket)


            Next
            lblStatus.Text = tblBucket.Rows.Count.ToString + "個のバケットが見つかりました。"
            gdvBucket.DataSource = New DataView(tblBucket)
            gdvBucket.DataBind()

        Else
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            lblStatus.Text = "取得に失敗しました。" + vbTab + jsonObj("reason")

        End If
    End Sub
End Class

データグリッドに選択列を追加

デザインビューでデータグリッドを選択し、GridViewタスクから「列の編集」を選択します。
HyperLinkFieldを追加し、
DataNavigateUrlFields  に バケットキー
DataNavigateUrlFormatString に ~/WebForm5.aspx?BucketKey={0}
HeaderText に 詳細表示
Text に 選択

を設定します。
選択列の追加
バケットを選択したときに、次のページを呼び出すときにGridViewに表示されているデータセットテーブルの 「バケットキー」の値を受け渡します。DataNavigateUrlFormatStringには、DataNavigateUrlFieldにカンマ区切りで設定した文字列を、{0} {1}の書式で受け渡すことができます。

バケット内オブジェクト一覧

あらたなWebフォームを追加し、ラベル(lblBucketKey)とGridView(gdvObjects)を追加します。ページが遷移するときのデータの受け渡しは HttpRequestの Request.QueryStringを使います。(サンプルコードの冒頭の部分)
また、バケットの一覧を取得する部分は、バケットキーを使ってURLを作成するだけなので比較的簡単といえるでしょう。

サンプルコード

Public Class WebForm5
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


        '**********************************
        '     バケットキーを取得
        '**********************************
    
        Dim strBucketKey As String = Request.QueryString("BucketKey")
        lblBucketkey.Text = strBucketKey

        '**********************************
        '     アクセストークンを取得
        '**********************************

        'アクセストークンを取得す部分はこちらを参照してください。
        Dim acToken As String = mdlUtils.GetToken("data:read")
        If acToken = "" Then
            lblBucketkey.Text = "アクセストークンの取得に失敗しました。"
        End If

        '**********************************
        '     バケット内のオブジェクト
        '**********************************
        Dim strClient As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(strClient)

        Dim chkReq As New RestSharp.RestRequest()
        With chkReq
            .Resource = "oss/v2/buckets/" + strBucketKey + "/objects"
            .Method = RestSharp.Method.GET
            .AddParameter("Authorization", "Bearer " + acToken, RestSharp.ParameterType.HttpHeader)
            .AddParameter("Content-Type", "application/json", RestSharp.ParameterType.HttpHeader)
        End With

        Dim result As RestSharp.IRestResponse = _client.Execute(chkReq)

        '**********************************
        '     データグリッドに表示
        '**********************************
        If result.StatusCode = Net.HttpStatusCode.OK Then
            '成功した場合
            'データセットを定義
            Dim dsObjects As New DataSet("BucketList")
            Dim tblObjects As DataTable = dsObjects.Tables.Add("Table1")
            tblObjects.Columns.Add("オブジェクトキー", Type.GetType("System.String"))
            tblObjects.Columns.Add("オブジェクトID", Type.GetType("System.String"))
            tblObjects.Columns.Add("ロケーション", Type.GetType("System.String"))

            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"items"を取得しjArrayオブジェクトとする
            Dim itemArray As Newtonsoft.Json.Linq.JArray = jsonObj("items")
            '配列を走査する
            For Each item As Newtonsoft.Json.Linq.JObject In itemArray
                'オブジェクトキー
                Dim strObjectKey As String = item("objectKey")
                'オブジェクトID
                Dim strObjectId As String = item("objectId")
                'ロケーション
                Dim strLoacation As String = item("location")

                'データセット
                Dim rowObjects As DataRow = tblObjects.NewRow()
                rowObjects("オブジェクトキー") = strObjectKey
                rowObjects("オブジェクトID") = strObjectId
                rowObjects("ロケーション") = strLoacation
                tblObjects.Rows.Add(rowObjects)


            Next
            gdvObjects.DataSource = New DataView(tblObjects)
            gdvObjects.DataBind()

        End If

    End Sub

End Class

GridViewを使うことで、少し見栄えも改善されました。

2017年2月1日水曜日

ファイルのアップロード +VB.net

バケットにファイルをアップロードする


作成したバケットにファイルをアップロードします。必要な情報は

  • アクセストークン data:create または  data:write (既存のファイルは上書き)
  • バケットキー   ファイルをアップロードするバケット

です。ここでもRestSharpを使ってファイルをアップロードしてみます。ユーザーインターフェイスは前回のバケット一覧を少し改造して、下の図のようにしてみました。
WebForm3.aspx
[参照]ボタンを押して選択したファイルを、lbxBucketsで選択したバケットに[アップロード]ボタンでアップロードし、そのObjectIDを取得して表示する、というシナリオです。

サンプルコード


アップロードボタンのクリックイベントのハンドラを示します。

    Protected Sub btnUpload_Click(sender As Object, e As EventArgs) Handles btnUpload.Click

        '**********************************
        ' アップロードするファイルを取得
        '**********************************

        'ファイルが選択されているか?
        If FileUpload1.HasFile = False Then
            MsgBox("ファイルが選択されていません。", MsgBoxStyle.OkOnly)
            Exit Sub
        End If

        'バケットにアップロードするファイル
        'FileUploadで転送されたファイル
        Dim fileToUpload As HttpPostedFile = FileUpload1.PostedFile

        'ファイル名(インターネットエクスプローラはフルパスを返す)
        Dim strFullPath As String = fileToUpload.FileName

        'ファイル名だけ取り出す
        Dim strFileName As String = IO.Path.GetFileName(strFullPath)

        '①ファイル名をURLエンコードする
        Dim strObjectKey As String = System.Web.HttpUtility.UrlEncode(strFileName)

        'ファイルの内容を読んでByteの配列とする
        Dim fileData As Byte() = Nothing
        Using binaryReader As New IO.BinaryReader(fileToUpload.InputStream)
            fileData = binaryReader.ReadBytes(fileToUpload.ContentLength)
        End Using


        '現在選択しているバケットキーを取得
        Dim strBucketKey As String = lbxBuckets.SelectedValue

        '**********************************
        '     アクセストークンを取得
        '**********************************

        Dim acToken As String = mdlUtils.GetToken("data:write")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     ファイルをアップロード
        '**********************************
        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets/" + strBucketKey + "/objects/" + strObjectKey

            'メソッド
            .Method = RestSharp.Method.PUT

            'ヘッダー
            .AddHeader("Authorization", "Bearer " + acToken)

            'BODY
            .AddParameter("Content-Type", fileToUpload.ContentType)
            .AddParameter("Content-Length", fileToUpload.ContentLength)

            '②アップロードするファイルをリクエストボディに追加
            .AddParameter("requestBody", fileData, RestSharp.ParameterType.RequestBody)

        End With

        'リクエスト送信
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        '結果
        If result.StatusCode = Net.HttpStatusCode.OK Then

            'ObjectIdを取得する
            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            'objectId
            lblObjectId.Text = jsonObj("objectId")

        Else
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            lblObjectId.Text = jsonObj("reason")

        End If

    End Sub

ポイントは①のファイルの名前をエンコードすることを忘れないようにするところと、②のファイルをBODYにテンプルすところです。

大きなサイズのデータを送れるようにする


ASP.netのFileUploadコントロールは転送できるファイルサイズが4MB程度に制限されているので、これを300MB(300×1024=307200KB)に緩和します。

ソリューションエクスプローラで「Web.config」ファイルを開き、17行目あたりにある
<httpRuntime targetFramework="4.6"/>
の末尾の/の前をクリックし、maxRequestLength="307200"と追記します。4.6"の後ろにスペースを空けて、maxと打てばインテリセンスが働いて、maxRequestを探すことができます。

  <system.web>
    <authentication mode="None" />
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.6" />
    <httpRuntime targetFramework="4.6" maxRequestLength="307200" />
    <pages>
      <namespaces>
     ・・・・

実行する


デバッグ起動してバケットと、アップロードするファイルを選択して「アップロード」ボタンを押すと、ファイルサイズによっては時間がかかりますが、うまくいけばオブジェクトIDが返ってきます。