Download an Attachment

Purpose

To download a file attached to a record.

Request Details

Request URL

https://www.zohoapis.com/crm/v2/{module_api_name}/{record_id}/Attachments/{attachment_id}

Supported modules

Leads, Accounts, Contacts, Deals, Campaigns, Tasks, Cases, Events, Solutions, Products, Vendors, Price Books, Quotes, Sales Orders, Purchase Orders, Invoices, Custom, and Notes

Header

Authorization: Zoho-oauthtoken d92d4xxxxxxxxxxxxx15f52

Scope

scope=ZohoCRM.modules.ALL
(or)
scope=ZohoCRM.modules.{module_name}.{operation_type}
(and)
scope=ZohoCRM.modules.attachments.{operation_type}

Possible module names

leads, accounts, contacts, deals, campaigns, tasks, cases, events, solutions, products, vendors, pricebooks, quotes, salesorders, purchaseorders, invoices, custom, notes

Possible operation types

ALL - Full access to attachments
READ - Get attachment data

Possible Errors

  • INVALID_MODULEHTTP 400

    The module name given seems to be invalid
    Resolution: You have specified an invalid module name or there is no tab permission, or the module could have been removed from the available modules. Specify a valid module API name.

  • INVALID_MODULEHTTP 400

    The given module is not supported in API
    Resolution: The modules such as Documents and Projects are not supported in the current API. (This error will not be shown, once these modules are been supported). Specify a valid module API name.

  • INVALID_URL_PATTERNHTTP 404

    Please check if the URL trying to access is a correct one
    Resolution: The request URL specified is incorrect. Specify a valid request URL. Refer to request URL section above.

  • OAUTH_SCOPE_MISMATCHHTTP 401

    Unauthorized
    Resolution: Client does not have ZohoCRM.modules.attachments.READ scope. Create a new client with valid scope. Refer to scope section above.

  • NO_PERMISSIONHTTP 403

    Permission denied to download attachment
    Resolution: The user does not have permission to download attachments. Contact your system administrator.

  • INTERNAL_ERRORHTTP 500

    Internal Server Error
    Resolution: Unexpected and unhandled exception in Server. Contact support team.

  • INVALID_REQUEST_METHODHTTP 400

    The http request method type is not a valid one
    Resolution: You have specified an invalid HTTP method to access the API URL. Specify a valid request method. Refer to endpoints section above.

  • AUTHORIZATION_FAILEDHTTP 400

    User does not have sufficient privilege to download attachments
    Resolution: The user does not have the permission to download attachments. Contact your system administrator.

Sample Request

Copiedcurl "https://www.zohoapis.com/crm/v2/Leads/100023009/Attachments/100013547"
-X GET
-H "Authorization: Zoho-oauthtoken 1000.8cb99dxxxxxxxxxxxxx9be93.9b8xxxxxxxxxxxxxxxf"
3.0.08.0
CopiedString moduleAPIName = "Leads";
Long recordId = 3477061000005177002L;
Long attachmentId = 3477061000005177023L;
String destinationFolder = "/Users/user_name/Desktop";

//Get instance of AttachmentsOperations Class that takes moduleAPIName and recordId as parameter
AttachmentsOperations attachmentsOperations = new AttachmentsOperations(moduleAPIName, recordId);

//Call downloadAttachment method that takes attachmentId as parameters
APIResponse < ResponseHandler > response = attachmentOperations.downloadAttachment(attachmentId);
Copiedimport java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
public class DownloadanAttachment 
{	
	public static void main(String[] args) 
	{
		try
		{
			HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
			SSLContext sslContext = SSLContext.getDefault();
			SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
			CloseableHttpClient httpclient = httpClientBuilder.setSSLSocketFactory(sslConnectionSocketFactory).build();
			URIBuilder uriBuilder = new URIBuilder("https://www.zohoapis.com/crm/v2/Leads/34770617711001/Attachments/34770617783004");
			HttpUriRequest requestObj = new HttpGet(uriBuilder.build());
			requestObj.addHeader("Authorization", "Zoho-oauthtoken 1000.xxxxxxx.xxxxxxx");
			HttpResponse response = httpclient.execute(requestObj);
			HttpEntity responseEntity = response.getEntity();
			System.out.println("HTTP Status Code : " + response.getStatusLine().getStatusCode());
			if(responseEntity != null)
			{
				if(response.containsHeader("Content-Disposition"))
				{
					String contentDisposition = response.getFirstHeader("Content-Disposition").getValue();
					String fileName = contentDisposition.split("=")[1];
					if(fileName.contains("''"))
			        {
			            fileName = fileName.split("''")[1];
			        }
					if(fileName.contains("\""))
			        {
			        	fileName = fileName.replace("\"", "");
			        }
					//Create a file instance with the absolute_file_path
					File file = new File("/Users/username/Desktop" + File.separatorChar + fileName);
					//Get InputStream from the response
					InputStream is = responseEntity.getContent();
					//Create an OutputStream for the destination file
					OutputStream os = new FileOutputStream(file);
					byte[] buffer = new byte[1024];
			        int bytesRead;
			        //read the InputStream till the end
			        while((bytesRead = is.read(buffer)) != -1)
			        {
			        	//write data to OutputStream
			        	os.write(buffer, 0, bytesRead);
			        }
			        //Close the InputStream
			        is.close();
			        //Flush and close the OutputStream
			        os.flush();
			        os.close();
				}
				else
				{
					Object responseObject = EntityUtils.toString(responseEntity);
					String responseString = responseObject.toString();
					System.out.println(responseString);
				}
			}
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
}
3.0.07.x
Copied//Get instance of AttachmentsOperations Class that takes recordId and moduleAPIName as parameter
$attachmentOperations = new AttachmentsOperations($moduleAPIName, $recordId);
//Call downloadAttachment method that takes attachmentId as parameters
$response = $attachmentOperations->downloadAttachment($attachmentId);
Copied<?php
class DownloadAttachment{
    
    public function execute(){
        $curl_pointer = curl_init();
        
        $curl_options = array();
        $url = "https://www.zohoapis.com/crm/v2/Leads/3524035495065/Attachments/35240336020005";
       
        $curl_options[CURLOPT_URL] = $url;
        $curl_options[CURLOPT_RETURNTRANSFER] = true;
        $curl_options[CURLOPT_HEADER] = 1;
        $curl_options[CURLOPT_CUSTOMREQUEST] = "GET";
        $headersArray = array();
        $headersArray[] = "Authorization". ":" . "Zoho-oauthtoken " ."1000.8cb99dxxxxxxxxxxxxx9be93.9b8xxxxxxxxxxxxxxxf";
        
        $curl_options[CURLOPT_HTTPHEADER]=$headersArray;
        
        curl_setopt_array($curl_pointer, $curl_options);
        
        $result = curl_exec($curl_pointer);
        $responseInfo = curl_getinfo($curl_pointer);
        curl_close($curl_pointer);
        list ($headers, $content) = explode("\r\n\r\n", $result, 2);
        if(strpos($headers," 100 Continue")!==false){
            list( $headers, $content) = explode( "\r\n\r\n", $content , 2);
        }
        $headerArray = (explode("\r\n", $headers, 50));
        $headerMap = array();
        foreach ($headerArray as $key) {
            if (strpos($key, ":") != false) {
                $firstHalf = substr($key, 0, strpos($key, ":"));
                $secondHalf = substr($key, strpos($key, ":") + 1);
                $headerMap[$firstHalf] = trim($secondHalf);
            }
        }
        $response = $content;
        if ($response == null && $responseInfo['http_code'] != 204) {
            list ($headers, $content) = explode("\r\n\r\n", $content, 2);
            $response = json_decode($content, true);
        }
        $contentDisp = $headerMap['Content-Disposition'];
        $fileName = substr($contentDisp, strrpos($contentDisp, "'") + 1, strlen($contentDisp));
        
        if (strpos($fileName, "=") !== false)
        {
            $fileName = substr($fileName, strrpos($fileName, "=") + 1, strlen($fileName));
            
            $fileName = str_replace(array(
                '\'',
                '"'
            ), '', $fileName);
        }
        $filePath = "/Users/test/PHP/PHPNativeSampleCode/";
        $fp = fopen($filePath . $fileName, "w"); // $filePath - absolute path where downloaded file has to be stored.
        $stream = $response;
        fputs($fp, $stream);
        fclose($fp);   
        
    }
    
}
(new DownloadAttachment())->execute();
3.0.08.x
Copied//Get instance of AttachmentsOperations Class that takes moduleAPIName and recordId as parameter
AttachmentsOperations attachmentsOperations = new AttachmentsOperations(moduleAPIName, recordId);
//Call DownloadAttachment method that takes attachmentId as parameters
APIResponse<API.Attachments.ResponseHandler> response = attachmentsOperations.DownloadAttachment(attachmentId);
Copiedusing System;
using System.IO;
using System.Net;
namespace Com.Zoho.Crm.API.Sample.RestAPI.FilesandAttachments
{
    public class DownloadanAttachment
    {
        public static void DownloadAttachment()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.zohoapis.com/crm/v2/Leads/34770617711001/Attachments/3477061763001");
            request.Method = "GET";
            request.Headers["Authorization"] = "Zoho-oauthtoken 1000.abfeXXXXXXXXXXX2asw.XXXXXXXXXXXXXXXXXXsdc2";
            request.KeepAlive = true;
            HttpWebResponse response;
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException e)
            {
                if (e.Response == null) { throw; }
                response = (HttpWebResponse)e.Response;
            }
            HttpWebResponse responseEntity = response;
            Console.WriteLine("HTTP Status Code : " + (int)response.StatusCode);
            WebHeaderCollection collection = responseEntity.Headers;
            string contentDisposition = collection["Content-Disposition"];
            if (contentDisposition != null)
            {
                string fileName = contentDisposition.Split(new string[] { "=" }, StringSplitOptions.None)[1];
                if (fileName.Contains("''"))
                {
                    fileName = fileName.Split(new string[] { "''" }, StringSplitOptions.None)[1];
                }
                fileName = fileName.Trim('\"');
                string fullFilePath = Path.Combine("/Users/abc-122/Desktop", fileName);
                using (FileStream outputFileStream = new FileStream(fullFilePath, FileMode.Create))
                {
                    responseEntity.GetResponseStream().CopyTo(outputFileStream);
                }
                responseEntity.Close();
            }
            else
            {
                string responsestring = new StreamReader(responseEntity.GetResponseStream()).ReadToEnd();
                responseEntity.Close();
                Console.WriteLine(responsestring);
            }
        }
    }
}
3.0.03.x.x
Copied# Get instance of AttachmentsOperations Class that takes module_api_name and record_id as parameter
attachments_operations = AttachmentsOperations(module_api_name, record_id)
# Call download_attachment method that takes attachment_id as parameters
response = attachments_operations.download_attachment(attachment_id)
Copieddef download_attachment():
    import requests
    import os

    url = 'https://www.zohoapis.com/crm/v2/Leads/3409643000002267003/Attachments/3409643000002847003'

    headers = {
        'Authorization': 'Zoho-oauthtoken 1000.04be928e4a96XXXXXXXXXXXXX68.0b9eXXXXXXXXXXXX60396e268'
    }

    response = requests.get(url=url, headers=headers)

    if response is not None:
        print("HTTP Status Code : " + str(response.status_code))

        if 'Content-Type' in response.headers:
            content_type = response.headers['Content-Type'].split(';')[0]

            if content_type == 'application/json':
                print(response.json())
            else:
                if 'Content-Disposition' in response.headers:
                    file_name = ''
                    content_disposition = response.headers['Content-Disposition']

                    if "'" in content_disposition:
                        start_index = content_disposition.rindex("'")
                        file_name = content_disposition[start_index + 1:]

                    elif '"' in content_disposition:
                        start_index = content_disposition.rindex('=')
                        file_name = content_disposition[start_index + 1:].replace('"', '')

                    destination_file = os.path.join(
                        '/Users/abc-123/Documents',
                        file_name)

                    with open(destination_file, 'wb') as f:
                        for chunk in response:
                            f.write(chunk)

download_attachment()
1.0.010.x
Copied//Get instance of AttachmentsOperations Class that takes recordId and moduleAPIName as parameter
let attachmentsOperations = new AttachmentsOperations(moduleAPIName, recordId);
//Call downloadAttachment method that takes attachmentId as parameters
let response = await attachmentsOperations.downloadAttachment(attachmentId);
Copiedasync function downloadAttachment() {
    const got = require("got");
    const fs = require("fs");
    const path = require("path");

    let url = 'https://www.zohoapis.com/crm/v2/Leads/3409643000002267003/Attachments/3409643000002847003'
    
    let headers = {
        Authorization : "Zoho-oauthtoken 1000.8cb99dxxxxxxxxxxxxx9be93.9b8xxxxxxxxxxxxxxxf"
    }

    let requestDetails = {
        method : "GET",
        headers : headers,
        throwHttpErrors : false
    }

    let response = await got(url, requestDetails)
    
    if(response != null) {
        console.log(response.statusCode);
        
        if(response.headers.hasOwnProperty('content-type')) {
            let contentType = response.headers['content-type'].split(";")[0];

            if(contentType == 'application/json') {
                console.log(response.body);
            }
            else {
                let fileName = "";

                let contentDisposition = (response.headers['content-disposition']);

                if(contentDisposition.includes("'")){
                    let startIndex = contentDisposition.lastIndexOf("'");

                    fileName = contentDisposition.substring(startIndex + 1);
                }
                else if(contentDisposition.includes("\"")){
                    let startIndex = contentDisposition.lastIndexOf("=");

                    fileName = contentDisposition.substring(startIndex + 1).replace(/"/g, "");
                }

                fileName = path.join("/Users/abc-123/Documents/SDK/nodejs/zohocrm-nodejs-sdk", fileName);

                fs.writeFileSync(fileName, response.rawBody);
            }
        }
    }
}
downloadAttachment()
2.02.x.x
Copied# """
ao = Attachments::AttachmentsOperations.new(module_api_name,record_id)
response = ao.download_attachment(attachment_id)
Copiedclass DownloadAttachment 

    def execute
      
        url = "https://www.zohoapis.com/crm/v2/Leads/3524033000005495065/Attachments/3524033000006019011"
        url = URI(url)
        req = Net::HTTP::Get.new(url.request_uri)
        http = Net::HTTP.new(url.host, url.port)
        http.use_ssl = true
        headers={}
        headers["Authorization"]="Zoho-oauthtoken 1000.50XXXXXXXXX&77e3a.44XXXXXXXXX8353"
        headers&.each { |key, value| req.add_field(key, value) }   
        
        response=http.request(req)
        file_name = response.to_hash["content-disposition"][0].split('=')[1]

        file_name = file_name.split("''")[1] if file_name.include? "''"

        file_name = file_name.gsub('"', '') if file_name.include? '"'

        status_code = response.code.to_i
        headers = response.each_header.to_h
        print status_code
        print headers
        unless response.body.nil?
            File.open("/Users/test/RUBY/RUBYNativeSampleCode/"+file_name, 'w') { |file| file.write(response.body) }
        end
    end
end
DownloadAttachment.new.execute
1.0.0ES6
Copied//Get instance of AttachmentsOperations Class that takes recordId and moduleAPIName as parameter
let attachmentsOperations = new ZCRM.Attachment.Operations(moduleAPIName, recordId);
//Call downloadAttachment method that takes attachmentId as parameters
let response = await attachmentsOperations.downloadAttachment(attachmentId);
Copiedvar listener = 0;
class DownloadanAttachment {

	async downloadAttachment()	{
		var url = "https://www.zohoapis.com/crm/v2/Leads/34770617711001/Attachments/34770619080486"
        var parameters = new Map()
        var headers = new Map()
        var token = {
            clientId:"1000.NPY9M1V0XXXXXXXXXXXXXXXXXXXF7H",
            redirectUrl:"http://127.0.0.1:5500/redirect.html",
            scope:"ZohoCRM.users.ALL,ZohoCRM.bulk.read,ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,Aaaserver.profile.Read,ZohoCRM.org.ALL,profile.userphoto.READ,ZohoFiles.files.ALL,ZohoCRM.bulk.ALL,ZohoCRM.settings.variable_groups.ALL"
        }
        var accesstoken = await new DownloadanAttachment().getToken(token)
        headers.set("Authorization", "Zoho-oauthtoken " + accesstoken)
        var requestMethod = "GET"
        var reqBody = null
        var params = "";
        parameters.forEach(function(value, key) {
            if (parameters.has(key)) {
                if (params) {
                    params = params + key + '=' + value + '&';
                }
                else {
                    params = key + '=' + value + '&';
                }
            }
        });
        var apiHeaders = {};
        if(headers) {
            headers.forEach(function(value, key) {
                apiHeaders[key] = value;
            });
        }
        if (params.length > 0){
            url = url + '?' + params.substring(0, params.length - 1);
        }
        var requestObj = {
            uri : url,
            method : requestMethod,
            headers : apiHeaders,
            body : JSON.stringify(reqBody),
            encoding: "utf8",
            allowGetBody : true,
			throwHttpErrors : false
        };
        var result = await new DownloadanAttachment().makeAPICall(requestObj);
        console.log(result.status)
        console.log(result.response)
        var filename;

        var disposition = result.getResponseHeader('content-disposition');//No I18N

        if (disposition && disposition.indexOf('attachment') !== -1) {

            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;

            var matches = filenameRegex.exec(disposition);

            if (matches != null && matches[1]) {

                filename = matches[1].replace(/['"]/g, '');

                filename = filename.replace('UTF-8','');
            }
        }
        let readStream = result.response;

        var url = URL.createObjectURL(readStream);

        var ttt = document.createElement('a');

        ttt.href = url;

        ttt.download = filename;

        ttt.click();
	}

    async getToken(token) {

        if(listener == 0) {

            window.addEventListener("storage", function(reponse) {
                if(reponse.key === "access_token" && (reponse.oldValue != reponse.newValue || reponse.oldValue == null)){
                    location.reload();
                }
                if(reponse.key === "access_token"){

                    sessionStorage.removeItem("__auth_process");
                }
            }, false);
            listener = 1;
            if(sessionStorage.getItem("__auth_process")) {
                sessionStorage.removeItem("__auth_process");
            }
        }
        ["granted_for_session", "access_token","expires_in","expires_in_sec","location","api_domain","state","__token_init","__auth_process"].forEach(function (k) {
            var isKeyExists = localStorage.hasOwnProperty(k);
            if(isKeyExists) {
                sessionStorage.setItem(k, localStorage[k]);
            }
            localStorage.removeItem(k);
        });
        var valueInStore = sessionStorage.getItem("access_token");
        var tokenInit = sessionStorage.getItem("__token_init");
        if(tokenInit != null && valueInStore != null && Date.now() >= parseInt(tokenInit) + 59 * 60 * 1000){ // check after 59th minute
            valueInStore = null;
            sessionStorage.removeItem("access_token");
        }

        var auth_process = sessionStorage.getItem("__auth_process");
        if ((valueInStore == null && auth_process == null) || (valueInStore == 'undefined' && (auth_process == null || auth_process == "true"))) {
            var accountsUrl = "https://accounts.zoho.com/oauth/v2/auth"
            var clientId;
            var scope;
            var redirectUrl;
            if(token != null) {
                clientId = token.clientId;
                scope = token.scope;
                redirectUrl = token.redirectUrl;
            }

            var fullGrant = sessionStorage.getItem("full_grant");
            var grantedForSession = sessionStorage.getItem("granted_for_session");
            if(sessionStorage.getItem("__token_init") != null && ((fullGrant != null && "true" == full_grant) || (grantedForSession != null && "true" == grantedForSession))) {
                accountsUrl += '/refresh';
            }
            if (clientId && scope) {
                sessionStorage.setItem("__token_init", Date.now());
                sessionStorage.removeItem("access_token");
                sessionStorage.setItem("__auth_process", "true");
                window.open(accountsUrl + "?" + "scope" + "=" + scope + "&"+ "client_id" +"=" + clientId + "&response_type=token&state=zohocrmclient&redirect_uri=" + redirectUrl);
                ["granted_for_session", "access_token","expires_in","expires_in_sec","location","api_domain","state","__token_init","__auth_process"].forEach(function (k) {
                    var isKeyExists = localStorage.hasOwnProperty(k);
                    if(isKeyExists){
                        sessionStorage.setItem(k, localStorage[k]);
                    }
                    localStorage.removeItem(k);
                });
                valueInStore = sessionStorage.getItem("access_token");
            }
        }
        if(token != null && valueInStore != 'undefined'){
            token.accessToken = valueInStore;
        }
        return token.accessToken;
    }

    async makeAPICall(requestDetails) {
        return new Promise(function (resolve, reject) {
            var body, xhr, i;
            body = requestDetails.body || null;
            xhr = new XMLHttpRequest();
            xhr.withCredentials = true;
            xhr.open(requestDetails.method, requestDetails.uri, true);
            for (i in requestDetails.headers) {
                xhr.setRequestHeader(i, requestDetails.headers[i]);
            }
            xhr.responseType = "blob";
            xhr.send(body);
            xhr.onreadystatechange = function() {
                if(xhr.readyState == 4) {
                    resolve(xhr);
                }
            }
        })
    }
}
Copiedresponse = invokeurl
[
	url: "https://www.zohoapis.com/crm/v2/Leads/100023009/Attachments/100013547"
	type: GET
	connection:"crm_oauth_connection"
];
info response;

The required file will be downloaded.