Let the platform do the work

How to Manipulate File Attachments

Overview

A PHP example demonstrating how to attach a file to a record using the v11 <module>/:record/file/:field REST POST API endpoint, then retrieve it with the GET endpoint.

Manipulating File Attachments

Authenticating

First, you will need to authenticate to the Sugar API. An example is shown below:

  <?php

$instance_url = "http://{site_url}/rest/v11";
$username = "admin";
$password = "password";

//Login - POST /oauth2/token
$auth_url = $instance_url . "/oauth2/token";

$oauth2_token_arguments = array(
    "grant_type" => "password",
    //client id - default is sugar. 
    //It is recommended to create your own in Admin > OAuth Keys
    "client_id" => "sugar", 
    "client_secret" => "",
    "username" => $username,
    "password" => $password,
    //platform type - default is base.
    //It is recommend to change the platform to a custom name such as "custom_api" to avoid authentication conflicts.
    "platform" => "custom_api" 
);

$auth_request = curl_init($auth_url);
curl_setopt($auth_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($auth_request, CURLOPT_HEADER, false);
curl_setopt($auth_request, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($auth_request, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($auth_request, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($auth_request, CURLOPT_HTTPHEADER, array(
    "Content-Type: application/json"
));

//convert arguments to json
$json_arguments = json_encode($oauth2_token_arguments);
curl_setopt($auth_request, CURLOPT_POSTFIELDS, $json_arguments);

//execute request
$oauth2_token_response = curl_exec($auth_request);

//decode oauth2 response to get token
$oauth2_token_response_obj = json_decode($oauth2_token_response);
$oauth_token = $oauth2_token_response_obj->access_token;

More information on authenticating can be found in the How to Authenticate and Log Out example and /oauth2/logout endpoint documentation.

Submitting a File Attachment

Next, we can create a Note record using the /<module endpoint, and then submit a File to the Note record using the /<module>/:record/file/:field endpoint.

  //Create Note - POST /
$url = $instance_url . "/Notes";
//Set up the Record details
$record = array(
    'name' => 'Test Note'
);

$curl_request = curl_init($url);
curl_setopt($curl_request, CURLOPT_POST, 1);
curl_setopt($curl_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($curl_request, CURLOPT_HEADER, false);
curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_request, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($curl_request, CURLOPT_HTTPHEADER, array(
    "Content-Type: application/json",
    "oauth-token: {$oauth_token}"
));

//convert arguments to json
$json_arguments = json_encode($record);
curl_setopt($curl_request, CURLOPT_POSTFIELDS, $json_arguments);
//execute request
$curl_response = curl_exec($curl_request);
//decode json
$noteRecord = json_decode($curl_response);

//display the created record
echo "Created Record: ". $noteRecord->id;

curl_close($curl_request);

//Add An Attachment to the Note
$url = $instance_url . "/Notes/{$noteRecord->id}/file/filename";

$file_arguments = array(
    "format" => "sugar-html-json",
    "delete_if_fails" => true,
    "oauth_token" => $oauth_token,
);

if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
    $file_arguments['filename'] = new CURLFile($path);
} else {
    $file_arguments['filename'] = '@'.$path;
}

$curl_request = curl_init($url);
curl_setopt($curl_request, CURLOPT_POST, 1);
curl_setopt($curl_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($curl_request, CURLOPT_HEADER, false);
curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_request, CURLOPT_FOLLOWLOCATION, 0);
//Do NOT set Content Type Header to JSON
curl_setopt($curl_request, CURLOPT_HTTPHEADER, array(
    "oauth-token: {$oauth_token}"
));

curl_setopt($curl_request, CURLOPT_POSTFIELDS, $file_arguments);
//execute request
$curl_response = curl_exec($curl_request);
//decode json
$noteRecord = json_decode($curl_response);
//print Note with attachment details
print_r($noteRecord);

curl_close($curl_request);

Note: As of PHP 5.6, the '@' upload modifier is disabled for security reasons by the CURLOPT_SAFE_UPLOAD option. We recommending using CURLFILE if using PHP >= 5.5, If you would prefer to use the upload modifier, you can set the CURLOPT_SAFE_UPLOAD option to false.

  curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);

Request

  //Raw Post - not json encoded
Array
(
    [format] => sugar-html-json
    [delete_if_fails] => 1
    [oauth_token] => 09eac950-c99e-4786-8b10-a3670f38fb3f
    [filename] => CURLFile Object
        (
            [name] => /Library/WebServer/Documents/file_attachment_manipulation/testfile.txt
            [mime] => 
            [postname] => 
        )
)

Response

  {
  "filename":{
     "content-type":"text\/plain",
     "content-length":13,
     "name":"upload.txt",
     "uri":"http:\/\/<site url>\/rest\/v11\/Notes\/7b49aebd-8734-9773-8ef1-53553fa369c7\/file\/filename"
  },
  "record":{
     "my_favorite":false,
     "following":true,
     "id":"7b49aebd-8734-9773-8ef1-53553fa369c7",
     "name":"My Note",
     "date_modified":"2014-04-21T11:53:53-04:00",
     "modified_user_id":"1",
     "modified_by_name":"admin",
     "created_by":"1",
     "created_by_name":"Administrator",
     "doc_owner":"",
     "user_favorites":[

     ],
     "description":"",
     "deleted":false,
     "assigned_user_id":"",
     "assigned_user_name":"",
     "team_count":"",
     "team_name":[
        {
           "id":1,
           "name":"Global",
           "name_2":"",
           "primary":true
        }
     ],
     "file_mime_type":"text\/plain",
     "file_url":"",
     "filename":"upload.txt",
     "parent_type":"",
     "parent_id":"",
     "contact_id":"",
     "portal_flag":false,
     "embed_flag":false,
     "parent_name":"",
     "contact_name":"",
     "contact_phone":"",
     "contact_email":"",
     "account_id":"",
     "opportunity_id":"",
     "acase_id":"",
     "lead_id":"",
     "product_id":"",
     "quote_id":"",
     "_acl":{
        "fields":{

        }
     },
     "_module":"Notes"
  }
}

Getting a File Attachment

Next, we can retrieve the file attachment stored in Sugar by utilizing the /<module>/:record/file/:field GET endpoint. The following code example, works when being accessed via a web browser, as it receives the response from Sugar, and sets the Headers received from Sugar on itself, so that the browser knows to download a file.

  //Get An Attachment on a Note
$url = $instance_url . "/Notes/{$noteRecord->id}/file/filename";

$curl_request = curl_init($url);
curl_setopt($curl_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
//Return Headers
curl_setopt($curl_request, CURLOPT_HEADER, true);
curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_request, CURLOPT_FOLLOWLOCATION, 0);
//DO NOT set Content Type Header to JSON
curl_setopt($curl_request, CURLOPT_HTTPHEADER, array(
    "oauth-token: {$oauth_token}"
));

//execute request
$curl_response = curl_exec($curl_request);

//Get Return Headers
$header_size = curl_getinfo($curl_request,CURLINFO_HEADER_SIZE);
$headers = substr($curl_response, 0, $header_size);

//Outputting the file contents
echo 'File saved to download.txt';
$file = substr($curl_response, $header_size);
file_put_contents('download.txt', $file);

curl_close($curl_request);

Request

http://{site_url}/rest/v11/Notes/bd490e66-2ea7-9349-19cf-535569400cca/file/filename

Note: GET request arguments are passed in the form of a query string.

Response

  HTTP/1.1 200 OK

Date: Wed, 12 Mar 2014 15:15:03 GMT

Server: Apache/2.2.22 (Unix) PHP/5.3.14 mod_ssl/2.2.22 OpenSSL/0.9.8o

X-Powered-By: PHP/5.3.14 ZendServer/5.0

Set-Cookie: ZDEDebuggerPresent=php,phtml,php3; path=/

Expires:

Cache-Control: max-age=0, private

Pragma:

Content-Disposition: attachment; filename="upload.txt"

X-Content-Type-Options: nosniff

ETag: d41d8cd98f00b204e9800998ecf8427e

Content-Length: 16

Connection: close

Content-Type: application/octet-stream



This is the file contents.

Download

You can download the full API example here.