传递多个输入文件时出错,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"
};
我已经问过关于这个的最后一个问题。我有一个 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"
};