function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Esha Sharma 3Esha Sharma 3 

Use Rest API to upload attachments

Hi Guys,

I am trying to hit below URL to use Attachments API and I am getting BAD Request. Can you help me with the right URL and point out if anything is missed.

builder = new PostMethod("https://gus,salesforce.com/" + "/services/data/v20.0/sobjects/Attachment/");
builder.setRequestHeader("Authorization","OAuth " + lr.getSessionId()); 
httpclient.executeMethod(builder);
System.out.println(builder.getStatusText());   << throws Bad Request
Esha Sharma 3Esha Sharma 3
Hi Guys,

This request is really urgent. Want somebody to really point out what is missing here?
Stanley JacobsStanley Jacobs
Hi,

I guess your endpoint is incorrect:
builder = new PostMethod("https://gus,salesforce.com/" + "/services/data/v20.0/sobjects/Attachment/");


Please take a look this link:
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart_oauth.htm

Go to section: Session ID Authorization

After login, salesforce will response Session ID & Instance, so you need to replace instance_name
 
curl https://instance_name.salesforce.com/services/data/v20.0/ -H 'Authorization: Bearer access_token'

Hope it works.
 
Esha Sharma 3Esha Sharma 3
This is what I changed in my code. Actually m getting sessiod_id from SOAP login. What to use the same session ID for Rest to upload attachments back. Below is the change I did:

 builder = new PostMethod("https://gus.salesforce.com/services/data/v20.0/");
 builder.setRequestHeader("Authorization","Bearer " + lr.getSessionId());  
httpclient.executeMethod(builder);
System.out.println(builder.getStatusText()); << Method not allowed
Stanley JacobsStanley Jacobs
Hi,

Some guideline:
- Convert your file to "Binary data"
- There's another http header Content-Type
- Construct newdocument.json as follow
 
--boundary_string
Content-Disposition: form-data; name="entity_document";
Content-Type: application/json

{  
    "Description" : "Marketing brochure for Q1 2011",
    "Keywords" : "marketing,sales,update",
    "FolderId" : "005D0000001GiU7",
    "Name" : "Marketing Brochure Q1",
    "Type" : "pdf"
}

--boundary_string
Content-Type: application/pdf
Content-Disposition: form-data; name="Body"; filename="2011Q1MktgBrochure.pdf"

Binary data goes here.

--boundary_string--


Click here  (https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm)for more complete steps
Esha Sharma 3Esha Sharma 3
In my code I am already making a SOAP call using  partner wsdl and call the login method that takes the username & password+securityToken and gets me the sessionId. I further want to use this sessionId and use Rest API attachments functinality. Can you please let me know how do I authorise using this session Id.
Stanley JacobsStanley Jacobs
Hi,

I would suggest you try simple functionality first, just to get familiar with REST API. You can try to create a record using rest api. Please follow this step by step: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_create.htm

What programming language do you use?

Another suggestion, you can use curl to test out REST API.
 
Esha Sharma 3Esha Sharma 3
Hi,

I am using Java for this. Can you also point out any working example for uploading file as "Binary data" using Rest. 
 
Stanley JacobsStanley Jacobs
Hi,

I don't have any working example. But here is the overview how to upload file using rest:
1. Login to salesforce, get session id & instance url
2. Prepare binary data and construct request body
Here is a link (http://blog.icodejava.com/248/how-to-base64-encode-or-base64-decode-a-file-in-java-using-apache-commons-codec/) to convert file to binary data. The binary data (base64 encoded) will be used in code below.
--boundary_string
Content-Disposition: form-data; name="entity_document";
Content-Type: application/json

{  
    "Description" : "Marketing brochure for Q1 2011",
    "Keywords" : "marketing,sales,update",
    "FolderId" : "005D0000001GiU7",
    "Name" : "Marketing Brochure Q1",
    "Type" : "pdf"
}

--boundary_string
Content-Type: application/pdf
Content-Disposition: form-data; name="Body"; filename="2011Q1MktgBrochure.pdf"

Binary data goes here ( put base64 encoded here. It will be like long random text/number )

--boundary_string--
Change description, keywords, folder id (mandatory), name and type
Change content-type & content-disposition as well

3. Set header, endpoint & session id
curl https://na1.salesforce.com/services/data/v23.0/sobjects/Document/ -H "Authorization: Bearer token" -H "Content-Type: multipart/form-data; boundary=\"boundary_string\"" --data-binary @newdocument.json

4. Execute callout rest api.
Salesforce will response either success or fail

Success
{
    "id" : "015D0000000N3ZZIA0",
    "errors" : [ ],
    "success" : true
}

Fail
{
    "fields" : [ "FolderId" ],
    "message" : "Folder ID: id value of incorrect type: 005D0000001GiU7",
    "errorCode" : "MALFORMED_ID"
}

 
Esha Sharma 3Esha Sharma 3
Hi,

Below is what I am doing:

        byte[] data = IOUtils.toByteArray(new FileInputStream(f));
                JSONObject content = new JSONObject(); 
                if (attachment != null) {
     content.put("Name", attachment); 
                }
                content.put("Body", new String(Base64.encode(data))); 
                content.put("ParentId", caseid);

                builder = new PostMethod("https://gus.salesforce.com/services/data/v20.0/sobjects/Attachment/");
                builder.setRequestEntity(new StringRequestEntity(content.toString(), "application/json", null));
                builder.setRequestHeader("Authorization","OAuth " + SessionId); 
                httpclient.executeMethod(builder);

This code works for me but for files for smaller size. I tried attaching file of 50+ MB and it threw bad request error for me. Can you please help. I need a solution for attaching files of larger size (around 1GB).

Regards,
​-Esha 
Neha AggrawalNeha Aggrawal
Hi,

If anyone is still looking for a solution, this is my code in PHP which uploads the attachment to Salesforce Documents.
 
<?php
//Add the below credentials to a separate file and call here using include
/***************oAuth2 Connected App Credentials************************************/
define("CLIENT_ID", "<Replace with your Client Id");
define("CLIENT_SECRET", "Replace with your Client Secret");
define("REDIRECT_URI", "Replace with Redirect URI");
define("LOGIN_URI", "Replace with your Login URI");
define("USER_NAME", "Your Username to login to Salesforce");
define("PASSWORD", "Your Password to login to Salesforce");
define("SECURITY_TOKEN", "Your security token");

/***************oAuth2 Connected App Credentials************************************/

$token_url = LOGIN_URI . "/services/oauth2/token";
//Login to Salesforce
$params =  "&grant_type=password"
    . "&client_id=" . CLIENT_ID
    . "&client_secret=" . CLIENT_SECRET
    . "&username=".USER_NAME
	."&password=".PASSWORD
	."&security_token=".SECURITY_TOKEN;

$curl = curl_init($token_url);

//curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);

$json_response = curl_exec($curl);

$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

if ( $status != 200 ) {
	$errstr="Error: call to token URL $token_url failed with status $status, response $json_response, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl).'<br>';
    //die("Error: call to token URL $token_url failed with status $status, response $json_response, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl));
}

curl_close($curl);

$response = json_decode($json_response, true);

$access_token = $response['access_token'];
$instance_url = $response['instance_url'];

if (!isset($access_token) || $access_token == "") {
	$errstr=$errstr." Error - access token missing from response!".'<br>';
   // die("Error - access token missing from response!");
}

if (!isset($instance_url) || $instance_url == "") {
	$errstr=$errstr." Error - instance URL missing from response!".'<br>';
   // die("Error - instance URL missing from response!");
}
//Get the user uploaded file
$file = $_FILES["file"]["tmp_name"];
$remote_file = $_FILES["file"]["name"];

$post_text=[
    "Description" => "Example File",
    "Keywords" =>  "Rest API File Upload",
    "FolderId" => "Replace with your Folder Id",
    "Name" => "Example Name",
    "Type" => "pdf",
	"body" => base64_encode(file_get_contents($file)),
];
$json_test=json_encode($post_text);
//Upload the file to Documents

$url=$instance_url."/services/data/v45.0/sobjects/Document/";
 $curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
 curl_setopt($curl, CURLOPT_HTTPHEADER,array("Authorization: OAuth $access_token","Content-type: application/json;boundary:a7V4kRcFA8E79pivMuV2tukQ85cmNKeoEgJgq"));
curl_setopt($curl, CURLOPT_POST, true);				   
    curl_setopt($curl, CURLOPT_VERBOSE, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $json_test);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLINFO_HEADER_OUT, true);
 $json_response = curl_exec($curl);

    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

    if ( $status != 201 ) {
        error_log("Error: call to URL $url failed with status $status, response $json_response, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl));
		//echo "error_message";
		exit;
    }
?>

This is my blog post with complete explanation: https://initaura.com/uploading-attachment-through-rest-api-salesforce-simple-working-solution/

Thanks and Regards, 
Neha Aggrawal
www.initaura.com - Everything Salesforce (https://www.initaura.com)
 
Gabriel Uchôa 7Gabriel Uchôa 7
Hi everyone,

I saw this post and the documentation of this API and I think that I'll need to use it.
I need to call the Document API but I don't understand the relationship between Document and ContentDocument. How can a relate both?
The requirement is I need to upload a file and associate it to a record. I already have the id of my record. How can I do this through API calls?

Regards,
​​​​​​​Gabriel Uchôa