cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - New to the community? Learn how to post a question and get help from PTC and industry experts! X

Can't Get Attachments through API

nborrerojr.
7-Bedrock

Can't Get Attachments through API

I can't get attachments to download through the API. I've tried adding "remote://" for both the "cwd" and "outputFile" options but nothing seems to point the command to my local computer. Any idea what I'm missing? Here is my code

private string localFolder = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
public void SaveAttachments(int IssueId, string FieldName, List<MKS.ManagedAPI.Item> AttachmentItems)
{
try
{
Command cmd = new Command("im", "extractattachments");
cmd.AddOption("hostname", hostServer);
cmd.AddOption("port", hostPort.ToString());
cmd.AddOption("user", userName);
cmd.AddOption("password", userPassword);
cmd.AddOption("cwd", Path.Combine("remote://", localFolder, IssueId.ToString()));
cmd.AddOption("outputFile", Path.Combine("remote://", localFolder, IssueId.ToString(), AttachmentItems[0].Id.ToString()));
cmd.AddOption("field", FieldName);
cmd.AddOption("issue", IssueId.ToString());

if (!APIFactory.IsInitialized)
APIFactory.MKSInitialize();

IIntegrationPoint ip = APIFactory.CreateIntegrationPoint(hostServer, hostPort, false, 4, 13);

ISession s = ip.CreateSession(userName, userPassword);
ICmdRunner cr = s.CreateCmdRunner();
IResponse r = cr.Execute(cmd);

cr.Dispose();
s.Dispose();
ip.Dispose();

}
catch (Exception ex)
{
ExceptionUtilities.LogException(ex, ex.Message);
}
finally
{
// Nothing.
}
}

The error I get is:

im: MKS124822: Invalid value provided for "outputFile": File paths must be rooted in /opt/plm/IntegrityServer10/data/tmp: outputFile is set to /opt/plm/IntegrityServer10/bin/C:\Users\userName\Documents\Visual Studio 2013\Projects\GATestExecutionClient\GATestExecutionClient\bin\x86\Debug\AppX/C:\Users\userName\AppData\Local\Packages\f6931c13-f27d-4e60-849e-9aabd681f391_4vvq3fpr0tnrp\LocalState\24682\icon_home_news_bug.png

1 ACCEPTED SOLUTION

Accepted Solutions

Figured it out. Path.Combine was stripping "remote://" from my path for some reason. I didn't know it would do that.

Also, if you just specify cwd then the response is "command failed." It appears that you need to actually specify the outputFile in order for it to work.

Working code in case anyone else runs into this:

private string localFolder = Windows.Storage.ApplicationData.Current.LocalFolder.Path;

for (int i = 0; i < AttachmentItems.Count; i++)
{
Command cmd = new Command("im", "extractattachments");
cmd.AddOption("hostname", hostServer);
cmd.AddOption("port", hostPort.ToString());
cmd.AddOption("user", userName);
cmd.AddOption("password", userPassword);

string savePath = "remote://" + localFolder;
//cmd.AddOption("cwd", Path.Combine(savePath, IssueId.ToString())); // <- This doesn't work
await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync(IssueId.ToString(), CreationCollisionOption.ReplaceExisting);
cmd.AddOption("outputFile", Path.Combine(savePath, IssueId.ToString(), AttachmentItems[i].Id.ToString()));
cmd.AddOption("field", FieldName);
cmd.AddOption("confirmoverwriteExisting");
cmd.AddOption("issue", IssueId.ToString());

if (!APIFactory.IsInitialized)
APIFactory.MKSInitialize();

IIntegrationPoint ip = APIFactory.CreateIntegrationPoint(hostServer, hostPort, false, 4, 13);

ISession s = ip.CreateSession(userName, userPassword);
ICmdRunner cr = s.CreateCmdRunner();
IResponse r = cr.Execute(cmd);

cr.Dispose();
s.Dispose();
ip.Dispose();
}

View solution in original post

4 REPLIES 4

Figured it out. Path.Combine was stripping "remote://" from my path for some reason. I didn't know it would do that.

Also, if you just specify cwd then the response is "command failed." It appears that you need to actually specify the outputFile in order for it to work.

Working code in case anyone else runs into this:

private string localFolder = Windows.Storage.ApplicationData.Current.LocalFolder.Path;

for (int i = 0; i < AttachmentItems.Count; i++)
{
Command cmd = new Command("im", "extractattachments");
cmd.AddOption("hostname", hostServer);
cmd.AddOption("port", hostPort.ToString());
cmd.AddOption("user", userName);
cmd.AddOption("password", userPassword);

string savePath = "remote://" + localFolder;
//cmd.AddOption("cwd", Path.Combine(savePath, IssueId.ToString())); // <- This doesn't work
await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync(IssueId.ToString(), CreationCollisionOption.ReplaceExisting);
cmd.AddOption("outputFile", Path.Combine(savePath, IssueId.ToString(), AttachmentItems[i].Id.ToString()));
cmd.AddOption("field", FieldName);
cmd.AddOption("confirmoverwriteExisting");
cmd.AddOption("issue", IssueId.ToString());

if (!APIFactory.IsInitialized)
APIFactory.MKSInitialize();

IIntegrationPoint ip = APIFactory.CreateIntegrationPoint(hostServer, hostPort, false, 4, 13);

ISession s = ip.CreateSession(userName, userPassword);
ICmdRunner cr = s.CreateCmdRunner();
IResponse r = cr.Execute(cmd);

cr.Dispose();
s.Dispose();
ip.Dispose();
}

I'm trying to do something similar in Java.  Your C# code above has been very helpful, but I'm having a problem with issues having more than one attachment:

com.mks.api.response.InvalidCommandSelectionException: This command accepts a selection of exactly one attachment.

Any idea what might be causing that error for an issue with multiple attachments?

Here's my code, it works for issues with single attachments.  The one difference is I'm not  using remote://.  I'd probably like to but I can find no documentation on how it's supposed to work, so I can live with saving all the attachments to data/tmp and sub directories on the server.

private Response extractAttachments( CmdRunner cmdRunner, MksIssue issue) throws APIException {

        Response respExtractAttachments  = null;

        if (issue.attachments != null && issue.attachments.size() > 0) {

            Iterator<Item> itItems = issue.attachments.getItems();

            while (itItems.hasNext()) {

                Item item = itItems.next();

                Command cmd = new Command();

                cmd.setApp( Command.IM );

                cmd.setCommandName( "extractattachments" );

                cmd.addOption( new Option("issue", issue.id));

                String outputFile = "/opt/MKS/IntegrityServer2009/data/tmp/extractedAttachments/mksAttachment." +

                        issue.type + "." + issue.id + "." + item.getDisplayId();

                cmd.addOption( new Option("outputFile",  outputFile));       

                cmd.addOption( new Option("field",  "Attachments"));       

                try {

                    respExtractAttachments  = cmdRunner.execute(cmd);

                } catch (APIException e) {

                    System.out.println(e.toString());

                    throw e;

                }

            }

        }

        return respExtractAttachments ;

    }

I think I ran into this same issue and my only solution was to loop through the attachments outside of the code and just call the method once for each attachment. I'll look into it more when I get a chance but I'm pretty sure that's what I did. I don't know why it has that issue though.

Found the problem -- I needed to do this:

   cmd.addSelection(item.getDisplayId());

item.getDisplayId() is the String name of the attachment.  It now produces a command line string like this:

   im extractattachments --user=myuser --port=9010 --hostname=myhost --issue=361 --outputFile=/opt/MKS/IntegrityServer2009/data/tmp/extractedAttachments/mksAttachment.Task.361.mydoc.doc --field=Attachments -- mydoc.doc

Top Tags