# How-to guides - Downloading files/documents

In this segment, we will be going through the creation of actions that download objects in our target application. Typically, The GET HTTP request method is used to send requests to download objects.

# Sample connector - Egnyte

{
  title: 'My Egnyte connector',

  # More connector code here
  actions: {
    download_object: {
      title: 'Download file from selected folder',

      description: lambda do |input, picklist_label|
        "Download <span class='provider'>file</span> in <span class='provider'>Egnyte</span>"
      end,

      help: 'Download file contents from selected folder in Egnyte.',

      input_fields: lambda do |object_definitions|
        [
          {
            name: 'file_path',
            label: 'File path',
            hint: 'Select path of file.',
            optional: false,
            control_type: 'tree',
            pick_list: 'file_path',
            toggle_hint: 'Select file',
            toggle_field: {
              name: 'file_path',
              type: 'string',
              control_type: 'text',
              label: 'File path',
              optional: false,
              toggle_hint: 'Use file path',
              hint: "Provide complete path of file. Example: <b>/Private/Sample/file.csv</b>"
            }
          }
        ]
      end,

      execute: lambda do |connection, input|
        file_path = input['file_path']&.gsub(/%2F/, '/')

        {
          "content": get("/pubapi/v1/fs-content/#{file_path}").headers('Accept' => '*/*').
            after_error_response(/.*/) do |_code, body, _header, message|
              error("#{message}: #{body}")
            end.response_format_raw.encode('ASCII-8BIT')
        }
      end,

      output_fields: lambda do |object_definitions|
        [
          { name: 'content' }
        ]
      end,

      sample_output: lambda do |connection, input|
        { "content": 'Hello World!' }
      end
    }
  # More connector code here
}

# Step 1 - Action title, subtitle, description, and help

The first step to making a good action is to properly communicate what the actions does, how it does it and to provide additional help to users. To do so, Workato allows you to define the title, description, and provide hints for an action. Quite simply, the title is the title of an action and the subtitle provides further details of the action. The description of the action then contains specifications and explanation on what the action accomplishes and in the context of the application it connects to. Finally, the help segment provides users any additional information required to make the action work.

To know more about this step, take a look at our SDK reference

# Step 2 - Define input fields

  input_fields: lambda do |object_definitions|
    [
      {
        name: 'file_path',
        label: 'File path',
        hint: 'Select path of file.',
        optional: false,
        control_type: 'tree',
        pick_list: 'file_path',
        toggle_hint: 'Select file',
        toggle_field: {
          name: 'file_path',
          type: 'string',
          control_type: 'text',
          label: 'File path',
          optional: false,
          toggle_hint: 'Use file path',
          hint: "Provide complete path of file. Example: <b>/Private/Sample/file.csv</b>"
        }
      }
    ]
  end

Download file input fields Download file input fields

This component tells Workato what fields to show to a user trying to retrieve an object. In the case of retrieving an account in Zuora for example, the user has to input the file_path of the file that a user wishes to download.

Object definitions

Note that object_definitions is passed in as an argument. Workato allows connector builders to supply the definitions of an object separately in the "object_definitions" key. This key is used when the definitions of an object are large and/or can be dynamically obtained.

To know more about this, take a look at our SDK reference

# Step 3 - Defining the execute key

The execute key tells Workato the endpoint to send the request to and using which HTTP request method. In this example, we send our request to /pubapi/v1/fs-content/#{file_path} using the Get method. We also append the after_error_response and response_format_raw methods to the request. The former, to catch any errors and to display them to users to aid in the debugging during recipe building.

For this get action, we first format the file_path the user generated by replacing any URL encoded value with the actual intended character, in this case, we replace %2F with /. We then append the formatted file_path to the API endpoint to tell Workato and subsequently Egnyte, which specific file to download.

In this example, we also append the response_format_raw to the request to tell Workato to expect a response in RAW format since we are expecting the response to be binary data (for example, PDFs, and images).

  execute: lambda do |connection, input|
    file_path = input['file_path']&.gsub(/%2F/, '/')

    {
      "content": get("/pubapi/v1/fs-content/#{file_path}").headers('Accept' => '*/*').
        after_error_response(/.*/) do |_code, body, _header, message|
          error("#{message}: #{body}")
        end.response_format_raw.encode('ASCII-8BIT')
    }
  end,

To know more about the execute key, take a look at our SDK reference

# Step 4 - Defining output fields

This section tells us what datapills to show as the output of the trigger. The name attributes of each datapill should match the keys in the output of the execute key.

  output_fields: lambda do |object_definitions|
    [
      { name: 'content' }
    ]
  end,

Download file output fields Download file output fields

To know more about the output fields key, take a look at our SDK reference

Object definitions

Note that object_definitions is passed in as an argument. Workato allows connector builders to supply the definitions of an object separately in the "object_definitions" key. This key is used when the definitions of an object are large and/or can be dynamically obtained.

To know more about this, take a look at our SDK reference

# Step 5 - Defining sample output

A supplementary component to a connector, the sample output key nonetheless greatly improves a user's experience by telling users the general data type and format of output fields to expect. This allows users to build recipes more quickly.

  sample_output: lambda do |connection, input|
    { "content": 'Hello World!' }
  end

To know more about the sample output key, take a look at our SDK reference