Search code examples
grailsrestful-authenticationdocumentum

Downloading content from URL without prompting for authentication in Grails


I am working on a web app programmed in Grails. I have a page used to display a certain report and these reports can contain attachments. The attachment is stored in documentum and currently, when the user clicks on it, it is only a link to the location in documentum where the attachment is stored and prompts the user for his credentials. My app has documentum credentials stored in the configuration file therefore I want to use those rather than forcing the user to enter his own credentials. I am using RESTful services to retrieve link but I am trying to find a way to use the link to download directly to the users computer.

private def getFileInfo(def id, def subject) {
  // product show view needs the following four lists to display the document information correctly
  def ATRReportInstance = ATRReport.findByTrackingNumber(id)
  def linkList = []
  def nameList = []
  def formatList = []
  def idList = []
  // open up a connection to the documentum server
  def doc = connectToDocumentum()

  if (!doc) return
  def rest = doc.rest
  def response = doc.response
  if (response.status == 200) {
    // retrieve the folder for this product (the name of this folder is the product's ID)
    def rObjectId = rest.get(documentumServer + "/repositories/" + documentumfilestore + "?dql=select r_object_id from dm_folder where any r_folder_path='" + atrreportfolderpath + "/" + id + "'") {
      auth authuser, authpass
    }
    // get the folder's ID from the folder object retrieved above
    def folderObjectID
    rObjectId.json.entries.each {
      entry - >
        folderObjectID = entry.content.properties.r_object_id
    }
    // get all of the documents in the product's MSDS folder using the folder ID retrieved above
    def resp = rest.get(documentumServer + "/repositories/" + documentumfilestore + "?dql=select r_object_id, object_name, a_content_type, subject from cbs_document where any i_folder_id= '" + folderObjectID + "'") {
      auth authuser, authpass
    }
    // cycle through the documents above to populate the four MSDS document information lists
    def x = 0
    resp.json.entries.each {
      entry - >
        if (entry.content.properties.subject == subject) {
          // get the document's content object from the document's ID
          def content = rest.get(documentumServer + "/repositories/" + documentumfilestore + "/objects/" + entry.content.properties.r_object_id + "/contents/content" + "?media-url-policy=local") {
            auth authuser, authpass
          }
          if (entry.content.properties.r_object_id != null && ATRReportInstance.inactiveFiles != null && ATRReportInstance.inactiveFiles.contains(entry.content.properties.r_object_id.toString())) {} else {
            linkList[x] = getLink(content.json.links, "enclosure")
            if (linkList[x].contains("format=msg"))
              linkList[x] = linkList[x].toString().substring(0, linkList[x].toString().indexOf("content-media")) + "content-media.msg"

            formatList[x] = entry.content.properties.a_content_type
            nameList[x] = entry.content.properties.object_name
            idList[x] = entry.content.properties.r_object_id
            x++
          }
        }
    }
    return [linkList: linkList, nameList: nameList, formatList: formatList, idList: idList]
  } else {
    // return null if documentum is unavailable
    flash.message = message(code: 'error.documentum.unavailable')
    return null
  }
}

I'm thinking writing another function that can take in a URL and download the document to the user might work, but I can't figure how to retrieve that document within Grails.


Solution

  • Here is the solution I implemented and that worked. It is a method that downloads a file in documentum using authentication credentials found in a configuration file.

    def exportAttachment() {
      //uses parameters from gsp file
      def url = params.url
      def name = params.name
      def format = params.format
      def extension
    
      //find proper extension
      for (s in documentumExtMap) {
        if (s.value.equals(format)) {
          extension = s.key
        }
      }
    
      def connection = new URL(url).openConnection()
      def remoteAuth = "Basic " + "${authuser}:${authpass}".bytes.encodeBase64()
      connection.setRequestProperty("Authorization", remoteAuth)
    
      def dataStream = connection.inputStream
    
      response.setContentType("application/octet-stream")
      response.setHeader('Content-disposition', 'Attachment; filename=' + name + '.' + extension)
      response.outputStream << dataStream
      response.outputStream.flush()
    }

    The method has three parameters: url, name, format.

    Url is the location of the file in documentum.

    Name is the name of the download client side

    Format is the type of file that is being downloaded. In my case, I had to use this to get the proper extension needed for the file.