Skip to main content
jacobb0002
February 15, 2021
Question

Download a file from a POST WebAPI call

  • February 15, 2021
  • 7 replies
  • 1 view

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
February 16, 2021

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
February 16, 2021

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
February 16, 2021

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.