Skip to main content
jacobb0002
New Participant
Feb 15, 2021 10:10 PM UTC
Question

Download a file from a POST WebAPI call

Hi!  

We are currently passing in a folderId over a WebAPI call to Appian - from there we are using a!startProcess to run the Document Zipper smart service to zip the folder and output the resulting documentId.

Is there a way to allow the resulting zip document to be downloaded via the WebAPI call, or will I have to use some workaround like using an additional GET method to pull the document after using POST to run the smart service?

Thanks!

7 replies

danny.verb
Employee
Feb 16, 2021 8:46 PM UTC

As long as you are chaining all the way through your process model this could be potentially possible. Then, in the onsuccess parameter of a!startProcess you should return:

a!httpResponse(
      headers: if(
        http!request.queryParameters.attachment,
        a!httpHeader(
          name: "Content-Disposition",
          value: concat(
            "attachment; filename=""",
            document(fv!processInfo.pv.documentId, "name"),
            ".",
            document(fv!processInfo.pv.documentId, "extension"),
            """"
          )
        ),
        {}
      ),
      body: todocument(fv!processInfo.pv.documentId)
    )

I have never done this and our API template creates the general download document requests as a GET but I think it is worth attempting. Otherwise, you will most likely need to make two calls.

jacobb0002
New Participant
Feb 16, 2021 8:53 PM UTC

Hi Danny, thanks for your reply!  My code almost perfectly mirrors yours (I modified the download document template).  I'll attach my code snippet, in case I am missing something; however I'm still getting the following error: "Not a valid Web API Response. Received: [Lcom.appiancorp.core.data.Record;@2127ea54".

a!localVariables(
  /* We don't want to serve arbitrary documents because it could be a security risk */
  local!extensionWhitelist: {"zip"},
  a!startProcess(
    processModel: cons!JSB_PM_SEND_DOCUMENT,
    processParameters: {folderId: http!request.formData.folderId},
    onSuccess: {
      if(
        /*
        * The path must be only 1 value, the document ID, and that ID must be a number.
        * Otherwise, we return a 404 Not Found
        */
        or(
          isnull(fv!processInfo.pv.zippedDocument),
          not(contains(local!extensionWhitelist, document(fv!processInfo.pv.zippedDocument, "extension")))
        ),
        a!httpResponse(
          statusCode: 404,
          body: "404 Not Found",
          headers: {}
        ),
        a!httpResponse(
          /*
          * If the query parameter "attachment" is set to true,
          * set an HTTP header that tells the client that the body of the response
          * should be downloaded. This overrides the default content-disposition
          * of "inline; filename=.". We will automatically
          * set the content-type and length.
          */
          headers: if(
            http!request.formData.attachment,
            a!httpHeader(
              name: "Content-Disposition",
              value: concat(
                "attachment; filename=""",
                document(fv!processInfo.pv.zippedDocumentId, "name"),
                ".",
                document(fv!processInfo.pv.zippedDocumentId, "extension"),
                """"
              )
            ),
            {}
          ),
          body: todocument(fv!processInfo.pv.zippedDocumentId)
        )
      )
    },
    onError: a!httpResponse(
      statusCode: 500,
      body: "500 There was an error starting the process",
      headers: {}
    )
  )
)

danny.verb
Employee
Feb 16, 2021 8:56 PM UTC

My guess is we only allow downloading a document via a GET. You can verify this by trying to download a document via GET and if it works just change your call to a POST. Given the low-latency to call Appian, calling back to back requests shouldn't add too much overhead.