Skip to main content
1-Visitor
April 21, 2015
Solved

Can't Get Attachments through API

  • April 21, 2015
  • 1 reply
  • 4211 views

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

    Best answer by nborrerojr.

    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();
    }

    1 reply

    nborrerojr.1-VisitorAuthorAnswer
    1-Visitor
    April 23, 2015

    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();
    }

    1-Visitor
    February 9, 2016

    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 ;

        }

    1-Visitor
    February 9, 2016

    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.