Convert document to base64 in response body for Web API Object (External client wants to call Appian Web API to retrieve documents)

Certified Lead Developer

Hi All,

We're interested in creating an Appian service using a Web API to return documents to an external client who will be processing these documents as part of a routine backend batch process.  While it's well documented how to convert a document to base64 in the request body for an outbound API call using an Integration object, I haven't found documentation on how Appian documents can be converted to a base64 string to return as part of the response body in an Appian Web API.  Curious if anyone else has had a similar use case and how they got around this.

Thanks!

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    This is the code from the pattern "Download Document" I selected when creating a new API. But this does only return the file. I am not aware that you can return a JSON structure that includes the base64 encoded file.

    EDIT: But you could include a number of additional parameters as headers.

    a!localVariables(
      local!pathArray: fn!cast('type!{http://www.appian.com/ae/types/2009}Text?list', http!request.pathSegments),
      local!document: tointeger(index(local!pathArray, 1, null)),
      /* We don't want to serve arbitrary documents because it could be a security risk */
      local!extensionWhitelist: {"pdf", "txt", "png", "jpg", "jpeg"},
      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(
          length(local!pathArray) <> 1,
          isnull(local!document),
          not(contains(local!extensionWhitelist, document(local!document, "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=<filename>.<extension>". We will automatically
          * set the content-type and length.
          */
          headers: if(
            http!request.queryParameters.attachment,
            a!httpHeader(
              name: "Content-Disposition",
              value: concat(
                "attachment; filename=""",
                document(local!document, "name"),
                ".",
                document(local!document, "extension"),
                """"
              )
            ),
            {}
          ),
          body: todocument(local!document)
        )
      )
    )

Reply
  • 0
    Certified Lead Developer

    This is the code from the pattern "Download Document" I selected when creating a new API. But this does only return the file. I am not aware that you can return a JSON structure that includes the base64 encoded file.

    EDIT: But you could include a number of additional parameters as headers.

    a!localVariables(
      local!pathArray: fn!cast('type!{http://www.appian.com/ae/types/2009}Text?list', http!request.pathSegments),
      local!document: tointeger(index(local!pathArray, 1, null)),
      /* We don't want to serve arbitrary documents because it could be a security risk */
      local!extensionWhitelist: {"pdf", "txt", "png", "jpg", "jpeg"},
      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(
          length(local!pathArray) <> 1,
          isnull(local!document),
          not(contains(local!extensionWhitelist, document(local!document, "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=<filename>.<extension>". We will automatically
          * set the content-type and length.
          */
          headers: if(
            http!request.queryParameters.attachment,
            a!httpHeader(
              name: "Content-Disposition",
              value: concat(
                "attachment; filename=""",
                document(local!document, "name"),
                ".",
                document(local!document, "extension"),
                """"
              )
            ),
            {}
          ),
          body: todocument(local!document)
        )
      )
    )

Children
  • 0
    Certified Lead Developer
    in reply to Stefan Helzle

    Thanks Stefan.  I think on our side the confusion was whether the resulting URL from that Web API object could be used to fetch the document as part of a backend process (and not have to convert the document to base64 string in the response body as a response).

    E.g., whether the client could do the following Python call and use the resulting document in their process:

    url = "appian-site.com/.../{AppianDocumentId}?attachment=true"
    payload={}
    headers = {...}
    response = requests.request("GET", url, headers=headers, data=payload)
    responseJson = response.json()
    document = responseJson['AppianDocument']

    Our external client has informed us that they should be able to use that URL to fetch the document, so I think we should be able to proceed.