AutoCAD I/O - 第二篇(Hello World)

上篇我们看到了AutoCAD /O的功能和基本原理,在申请到API key以后,就可以进行开发了。接触一个新技术,都会以一个精巧的例子起头,俗称 Hello World。但AutoCAD I/O Hello World并不是简单写个模板,弹出个对话框就ok了,不过也不用紧张,一起来看看。

AutoCAD I/O是web service,程序只要能发送HTTP请求即可。我们将这些HTTP请求的常用流程封装了一个.NET service reference。因此让我们以一个.NET程序开始I/O的旅行:

1. 创建C#控制台程序

创建一个C# 控制台程序,名为MyTestAutoCADIO。 添加service reference, 引入 https://developer.api.autodesk.com/autocad.io/v1,  并命名为 AcadIO。

AutoCAD I/O - 第二篇(Hello World)_第1张图片

添加 Newtonsoft.Json 引用,这是用来解析AutoCAD I/O登陆后的Json字,获取到口令(token)。


2. AutoCAD I/O认证

前篇提到,HTTP请求时,服务器端需要判断是否是合法用户提交的请求,因此,使用AutoCAD I/O第一步,就是认证。以下是第一步建立的工程,Main函数里填写的内容。包括这样的几步:
1. 创建与AutoCAD I/O通讯入口
2. 配置HTTP请求,调用认证服务。服务端口地址为: 
   https://developer.api.autodesk.com/authentication/v1/authenticate
3. 成功后,解析返回的Json字串,得到其中token的内容。

所谓token(口令)是当HTTP认证合法后,服务器交给请求者的一个通行证,在随后的HTTP请求中,都需要提供,让服务器得知请求的合法。这里封装的 SetHeader函数,可以配置HTTP请求头,这样随后的请求就不用总是填写token这个参数了。

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
 

namespace MyTestAutoCADIO
{
    class Program
    {    
        static void Main(string[] args)
        {
            //创建与AutoCAD IO 通讯的代理人口
            Uri uri = new Uri("https://developer.api.autodesk.com/autocad.io/v1/");
            //服务的容器
            var container = new AcadIO.Container(uri);
            //指定使用Json进行通讯
            container.Format.UseJson();
            //开发者的 API  key
            var clientId = "你自己的API key";
            //开发者的 API  secret
            var clientSecret = "你自己的API seret";
            //AutoCAD IO 返回的口令
            string token = null;

                       
            using (var client = new HttpClient())
            {
                //配置HTTP请求。其中有两个参数是开发者的API key和 secret
                var values = new List>();
                values.Add(new KeyValuePair("client_id", clientId));
                values.Add(new KeyValuePair("client_secret", clientSecret));
                values.Add(new KeyValuePair("grant_type", "client_credentials"));

                var requestContent = new FormUrlEncodedContent(values);

                //向AutoCADI/O发出认证请求
                //服务端点地址为: https://developer.api.autodesk.com/authentication/v1/authenticate
                var response = client.PostAsync("https://developer.api.autodesk.com/authentication/v1/authenticate", 
                                requestContent).Result;

                //得到响应,查看返回结果
                var responseContent = response.Content.ReadAsStringAsync().Result;
                //解析返回的Json字串
                var resValues = JsonConvert.DeserializeObject>(responseContent);
                //提取出口令(token)
                token = resValues["token_type"] + " " + resValues["access_token"];
            }

            //将口令设置到随后所有AutoCAD I/O相关请求的HTTP头
            if (!string.IsNullOrEmpty(token))
                container.SendingRequest2 += (sender, e) => e.RequestMessage.SetHeader("Authorization", token);

            //接下来可以进行AutoCAD I/O的其它操作
            //.....

        }
    }
}

可以编译执行这一部分,看看通过你的API key与secret能否认证成功。

AutoCAD I/O - 第二篇(Hello World)_第2张图片


3. 遍历Activity

Activity是规定具体对图纸做什么样的操作。AutoCAD I/O有Activity集合,类似一个篮子,存放Activity。一般是你自己创建的,也包含别人分享的Activity。对应的集合是AcadIO.Container.Activities。基于上面的代码框架,增加一个函数,并在Main函数中调用它。

 //接下来可以进行AutoCAD I/O的其它操作
 //.....
 
//遍历Activity
GetActivities(container); 

}//Main函数结尾

 static void GetActivities(AcadIO.Container container)
        {
            foreach (var act in container.Activities)
            {
                Console.WriteLine("{0} {1}", act.UserId, act.Id);

                Console.WriteLine(" Input Parameters:");
                foreach (var inputP in act.Parameters.InputParameters)
                {
                    Console.WriteLine("     {0}", inputP.Name);
                }
                Console.WriteLine(" Output Parameters:");
                foreach (var outputP in act.Parameters.OutputParameters)
                {
                    Console.WriteLine("     {0}", outputP.Name);
                } 
            }


每个Activity也有标识Id,UserId是AutoCAD I/O自动分配的Guid,而Id是在创建Activity时开发者给的名字。我这里的Activity如下,其中有一个分享型的是批处理DWG为PDF (PlotToPDF)。每个Activity都规定了输入参数和输出参数。例如PlotToPDF,输入参数名为“HostDwg”,输出参数名为"Result"。

AutoCAD I/O - 第二篇(Hello World)_第3张图片


注: 由于.NET封装了服务,所以从表面看我们直接调用了相关内容,但实际背后是发送的HTTP请求。

4.  执行批处理任务 ( WorkItem)

有了Activity,就可以构建批处理任务,也就是前篇提到的的WorkItem。规定DWG图纸在哪里,产生的结果放哪里,用哪个Activity进行操作。例如,如果我们要进行DWG转PDF的批处理,可以这样建立WorkItem。仍旧基于上面的代码,创建一个新函数。几点说明:

1. WorkItem不需要设置Id,AutoCAD I/O会自动分配

2. 输入参数的来源(也就是需要处理的DWG)可以是A360云存储里的,也可以是其它云存储。Resource规定之。访问云存储的文件,对应的云服务的授权,一般是一种签名后的URL。StorageProvider  = "A360"表明是A360的云存储,而StorageProvider = "Generic"表明是其它云存储。例如本例是我的亚马逊(AWS)上的一个文件。

3. 按照Activity的参数规定,提供文件。传出的结果,如果Resource= null,则将结果文件放到AutoCAD I/O存储中。

//接下来可以进行AutoCAD I/O的其它操作
 //.....
 
//遍历Activity
 GetActivities(container);

 //执行批处理任务 ( WorkItem)
 CreateWorkItem(container);

}//Main函数结尾


static void CreateWorkItem(AcadIO.Container container)
{
    //新建WorkItem
    var wi = new AcadIO.WorkItem()
    {
        UserId = "", //必须为空,AutoCAD I/O会自动分配Guid
        Id = "", //必须为空,AutoCAD I/O会自动分配Guid
        Arguments = new AcadIO.Arguments(),
        Version = 1,
        //用哪个Activity
        ActivityId = new AcadIO.EntityId() { UserId = "Shared", Id = "PlotToPDF" }
    };
    //设置输入参数
    wi.Arguments.InputArguments.Add(new AcadIO.Argument()
    {
        //对应Activity哪个参数 
        Name = "HostDwg",
        //来源。本例是AWS上的文件
        Resource = "https://xiaodongtemptestio.s3-ap-southeast-1.amazonaws.com/Lights.dwg?AWSAccessKeyId=XXXXXXXExpires=1429936154&Signature=SKgpVs2ebxRKngiv8AiWMHCkFLM%3D",
        //非A360数据源
        StorageProvider = "Generic" 
    });
    //设置输出参数
    wi.Arguments.OutputArguments.Add(new AcadIO.Argument()
    {
        //对应Activity哪个参数 
        Name = "Result",
        //非A360数据源
        StorageProvider = "Generic",
        //HTTP动作 - 将结果放到对应的云存储
        HttpVerb = "POST",
        //如果设置为null,则缺省放到AutoCAD I/O存储空间里
        Resource = null
    });

    //添加此WorkItem, 也就是开始启动任务
    container.AddToWorkItems(wi);
    container.SaveChanges();

    //看看AutoCAD I/O为WorkItem分配了什么Guid
    Console.WriteLine("UserId = {0}, Id= {1}", wi.UserId, wi.Id); 
            
    container.MergeOption = System.Data.Services.Client.MergeOption.OverwriteChanges;

    //等待,看看该任务WorkItem是否执行完毕
    do
    {
        System.Threading.Thread.Sleep(10000);
        wi = container.WorkItems.Where(p => p.UserId == wi.UserId && p.Id == wi.Id).SingleOrDefault();
    }
    while (wi.Status == "Pending" || wi.Status == "InProgress");

    if (wi.Status == "Succeeded")
    {
        //若成功结束,看看转换后的文件url
        Console.WriteLine("The result is downloadable at {0}", wi.Arguments.OutputArguments.First().Resource);
    }  
}

运行一下,若成功,则可以看到结果的文件的url,其实就是文件流。


AutoCAD I/O - 第二篇(Hello World)_第4张图片


5. 下载结果文件

前面的文件流,可以下载到本地机器。写个小函数。并在CreateWorkItem函数中调用。 

//等待,看看该任务WorkItem是否执行完毕
    do
    {
        System.Threading.Thread.Sleep(10000);
        wi = container.WorkItems.Where(p => p.UserId == wi.UserId && p.Id == wi.Id).SingleOrDefault();
    }
    while (wi.Status == "Pending" || wi.Status == "InProgress");

    if (wi.Status == "Succeeded")
    {
        //若成功结束,看看转换后的文件url
        Console.WriteLine("The result is downloadable at {0}", wi.Arguments.OutputArguments.First().Resource);

        //下载结果文件
        String localFilePath = String.Empty;
        if (!Download(wi.Arguments.OutputArguments.First().Resource.ToString(), ref localFilePath))
        {
            Console.WriteLine("failed to get the result file!");
        }
    }  
}//CreateWorkItem函数结尾

public static bool Download(String url, ref String localFilePath)
{
    try
    {
        if (String.IsNullOrEmpty(url))
            return false;

        // Load the url in web browser
        if (url.StartsWith("http://") || url.StartsWith("https://"))
        {
            //下载到我的文档文件夹
            String filename = Path.GetFileName(new Uri(url).AbsolutePath);
            localFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename);
            using (System.Net.WebClient wc = new System.Net.WebClient())
            {
                wc.DownloadFile(url, localFilePath);
            }

            if (!String.IsNullOrEmpty(localFilePath))
            {
                return true;
            }
        }
    }
    catch (System.UriFormatException)
    {
        Console.WriteLine(url + "could not be loaded.");
    }
    catch (System.Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    localFilePath = String.Empty;
    return false;
}







你可能感兴趣的:(AutoCAD)