传递多个输入文件时出错,Design Automation Revit dot net core

Error passing multiple input files, Design Automation Revit dot net core

我已经问过关于这个的最后一个问题。我有一个 rfa 文件和一个更大的 JSon 文件作为输入。当我调试时,它看起来完美地传递了所有值直到最后一行: WorkItemStatus workItemStatus = await _designAutomation.CreateWorkItemAsync(workItemSpec);

看起来 workItemSpec 有问题。请查看这些代码片段,请让我知道这里有什么问题。

来自 ForgeDesignAutomation.js 的代码片段如下:

    {
    var inputFileField = document.getElementById('inputFile');
    
    if (inputFileField.files.length === 0) { alert('Please select an input file'); return; }
    if ($('#activity').val() === null) { alert('Please select an activity'); return };
    var file = inputFileField.files[0];
    var inputFileField2 = document.getElementById('inputJsonFile');
    if (inputFileField2.files.length === 0) { alert('Please select an input file'); return; }
    var file2 = inputFileField2.files[0];
    let activityId = $('#activity').val();
    if (activityId == null)
    {
        alert('Please select an activity'); return
    };
    
    if (activityId.toLowerCase() === "_da4ractivity+dev")
       {
        startConnection(function () {
            var formData = new FormData();
            formData.append('inputFile', file);
            formData.append('inputJsonFile', file2);
            formData.append('data', JSON.stringify({
                activityName: $('#activity').val(),
                browerConnectionId: connectionId
            }));
        writeLog('Uploading input file...');
        $.ajax({
                url: 'api/forge/designautomation/workitems',
                data: formData,
                processData: false,
                contentType: false,
                type: 'POST',
                success: function (res)
                {
                    writeLog('Workitem started: ' + res.workItemId);
                }
            });
        });
    }
}```


code fraction from "CreateActivity" in DesignAutomationController.cs

```  Parameters = new Dictionary<string, Parameter>()
                    {
                        { "inputFile", new Parameter() { Description = "input file", LocalName = "$(inputFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } },
                        { "inputJsonFile", new Parameter() { Description = "input Json file", LocalName = "$(inputJsonFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } },
                        { "outputFile", new Parameter() { Description = "output file", LocalName = "outputFile." + engineAttributes.extension, Ondemand = false, Required = true, Verb = Verb.Put, Zip = false } }
                    }```

code fraction from "StartWorkitem" in DesignAutomationController.cs


``` [HttpPost]
        [Route("api/forge/designautomation/workitems")]
        public async Task<IActionResult> StartWorkitem([FromForm]StartWorkitemInput input)
        {
            // basic input validation
            JObject workItemData = JObject.Parse(input.data);
           
            string activityName = string.Format("{0}.{1}", NickName, workItemData["activityName"].Value<string>());
            string browerConnectionId = workItemData["browerConnectionId"].Value<string>();
            
            // save the file on the server
            var fileSavePath0 = Path.Combine(_env.ContentRootPath, Path.GetFileName(input.inputFile.FileName));
            using (var stream0 = new FileStream(fileSavePath0, FileMode.Create)) await input.inputFile.CopyToAsync(stream0);
            
            var fileSavePath1 = Path.Combine(_env.ContentRootPath, Path.GetFileName(input.inputJsonFile.FileName));
            using (var stream1 = new FileStream(fileSavePath1, FileMode.Create)) await input.inputJsonFile.CopyToAsync(stream1);


            //---------------------------------------------------------------------------------------------------------------------
            // OAuth token
            dynamic oauth = await OAuthController.GetInternalAsync();

            // upload file to OSS Bucket
            // 1. ensure bucket existis
            string bucketKey = NickName.ToLower() + "-designautomation";
            BucketsApi buckets = new BucketsApi();
            buckets.Configuration.AccessToken = oauth.access_token;
            try
            {
                PostBucketsPayload bucketPayload = new PostBucketsPayload(bucketKey, null, PostBucketsPayload.PolicyKeyEnum.Transient);
                await buckets.CreateBucketAsync(bucketPayload, "US");
            }
            catch { }; 
            
            // in case bucket already exists
            // 2. upload inputFile
            string inputFileNameOSS0 = string.Format("{0}_input_{1}", DateTime.Now.ToString("yyyyMMddhhmmss"), Path.GetFileName(input.inputFile.FileName)); // avoid overriding
            string inputFileNameOSS1 = string.Format("{0}_inputJson_{1}", DateTime.Now.ToString("yyyyMMddhhmmss"), Path.GetFileName(input.inputJsonFile.FileName)); // avoid overriding

            //string inputFileNameOSS = Path.GetFileName(input.inputFile.FileName); // avoid overriding


            ObjectsApi objects = new ObjectsApi();
            objects.Configuration.AccessToken = oauth.access_token;
            using (StreamReader streamReader = new StreamReader(fileSavePath0))
                await objects.UploadObjectAsync(bucketKey, inputFileNameOSS0, (int)streamReader.BaseStream.Length, streamReader.BaseStream, "application/octet-stream");
            System.IO.File.Delete(fileSavePath0);// delete server copy

            // prepare workitem arguments
            // 1. input file
            XrefTreeArgument inputFileArgument = new XrefTreeArgument()
            {
                Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, inputFileNameOSS0),
                Headers = new Dictionary<string, string>()
                 {
                     { "Authorization", "Bearer " + oauth.access_token }
                 }
            };

            using (StreamReader streamReader1 = new StreamReader(fileSavePath1))
                await objects.UploadObjectAsync(bucketKey, inputFileNameOSS1, (int)streamReader1.BaseStream.Length, streamReader1.BaseStream, "application/octet-stream");
            System.IO.File.Delete(fileSavePath1);// delete server copy

            // 1. input Json file
            XrefTreeArgument inputJsonArgument = new XrefTreeArgument()
            {
                Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, inputFileNameOSS1),
                Headers = new Dictionary<string, string>()
                 {
                     { "Authorization", "Bearer " + oauth.access_token }
                 }
            };

            
            // 3. output file
            string outputFileNameOSS = string.Format("{0}_output_{1}", DateTime.Now.ToString("yyyyMMddhhmmss"), Path.GetFileName(input.inputFile.FileName)); // avoid overriding
            XrefTreeArgument outputFileArgument = new XrefTreeArgument()
            {
                Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, outputFileNameOSS),
                Verb = Verb.Put,
                Headers = new Dictionary<string, string>()
                   {
                       {"Authorization", "Bearer " + oauth.access_token }
                   }
            };

           
            // prepare & submit workitem
            string callbackUrl = string.Format("{0}/api/forge/callback/designautomation?id={1}&outputFileName={2}", OAuthController.GetAppSetting("FORGE_WEBHOOK_URL"), browerConnectionId, outputFileNameOSS);
            WorkItem workItemSpec = new WorkItem()
            {
                ActivityId = activityName,
                Arguments = new Dictionary<string, IArgument>()
                {
                    { "inputFile", inputFileArgument },
                    { "inputJsonFile", inputJsonArgument },
                    { "outputFile", outputFileArgument },
                    { "onComplete", new XrefTreeArgument { Verb = Verb.Post, Url = callbackUrl } }
                }
            };
            WorkItemStatus workItemStatus = await _designAutomation.CreateWorkItemAsync(workItemSpec);
            return Ok(new { WorkItemId = workItemStatus.Id });
        }```





```/// <summary>
        /// Input for StartWorkitem
        /// </summary>
        public class StartWorkitemInput[![enter image description here][1]][1]
        {
            public IFormFile inputFile { get; set; }
            public IFormFile inputJsonFile { get; set; }
            public string data { get; set; }
        } ``` 


  [![enter image description here][1]][1]


  [1]: https://i.stack.imgur.com/GktUC.png

我注意到你的 activity 将 "inputFile"/"inputJsonFile" 的 "localName" 定义为 "$(inputFile)"/"$(inputJsonFile)"

Parameters = new Dictionary<string, Parameter>()
 {
     { "inputFile", new Parameter() { Description = "input file", LocalName = "$(inputFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } },
     { "inputJsonFile", new Parameter() { Description = "input Json file", LocalName = "$(inputJsonFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } }
 }

在作业过程中解析输入的命名时,这可能会导致一些问题。我建议您提供一个具体的文件名作为 WorkItem 参数的本地名称,然后重试。例如:

XrefTreeArgument inputJsonArgument = new XrefTreeArgument()
{
      Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, inputFileNameOSS1),
      Headers = new Dictionary<string, string>()
      {
         { "Authorization", "Bearer " + oauth.access_token }
      },
      // Note: if your appbunldes(addin) uses this json, this is the name your addin should know 
      LocalName = "inputJson.json" 
};