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
ssuede7ssuede7 

Download an attachment PHP code example?

Can anyone clue me in on how to bring an attachment down from SF so my users can download to their machine?

 

I understand how to query or retrieve from the attachment object and also understand the need to decode the base64 encoded body, but my attempts have gone nowhere thus far.  Here is my code:

//SF Header stuff require_once ($_SERVER["DOCUMENT_ROOT"].'/system/header_sforce.php'); //Grab an Attachement Id from the reqeust object $attid = $_REQUEST['attid']; //Query SF for the desired attachment $query = 'SELECT Id, ParentId, Name, BodyLength, Body FROM Attachment WHERE Id = \''.$attid.'\' '; $queryObject = $mySforceConnection->query($query); //Probably have some header() methods here echo base64_decode($queryObject->records[0]->Body);

 

I know it's not elegant, right now I'm just trying to get a rudimentary download working.  If someone could just cut and paste an example of some working code from their app that would be so awesome.

 

Thanks in advance.

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
ssuede7ssuede7

OK, my problem was the Content-Length header.  You can see in my second post and typo'd the array key name.  I fixed that and gave it try and now everything is working great.  

 

My only issue now is that when I upload attachment the ContentType field is not populated with anything.  So when I download I am limited "application/force-download" for eveything.  Is there a proper way to manage ContentType in the upload and download process?

 

Thanks

 

Below is my code thus far:

require_once ($_SERVER["DOCUMENT_ROOT"].'/system/header_sforce.php'); $attid = $_REQUEST['attid']; $query = 'SELECT Id, ParentId, Name, BodyLength, Body FROM Attachment WHERE Id = \''.$attid.'\' '; $queryObject = $mySforceConnection->query($query); $file = $queryObject->records[0]->Body; $name = $queryObject->records[0]->Name; $length = $queryObject->records[0]->BodyLength; header('Content-Type: application/force-download'); header('Content-Disposition: inline; filename="'.$name.'"'); header('Content-Length: '.$length); if($file) echo $file;

 

 

 

 

 

All Answers

ssuede7ssuede7

OK, here's an update.  Apparently putting the Body data into a variable first ($file) has made a large difference.  The following code works.... sort of...

 

 

require_once ($_SERVER["DOCUMENT_ROOT"].'/system/header_sforce.php'); $attid = $_REQUEST['attid']; $query = 'SELECT Id, ParentId, Name, BodyLength, Body FROM Attachment WHERE Id = \''.$attid.'\' '; $queryObject = $mySforceConnection->query($query); $file = $queryObject->records[0]->Body; $name = $queryObject->records[0]->Name; //$length = $$queryObject->records[0]->Length; header('Content-Type: application/force-download'); header('Content-Disposition: inline; filename="'.$name.'"'); //header('Content-Length: '.$length.';'); if($file) echo $file;

 The only problem I'm having now is one of my "test" attachments is a docx.  The whole thing is able to get down to my machine but when I open it Word detects errors and runs a fix, then it opens fine.  I'm guessing the problem may be that I am not declaring the file length in the header.  When I try to do this nothing downloads properly so for now I have left it commented out.

 

I would still love to see an example of how someone else has done this in their app.  Or if anyone can comment on my approach and offer suggestions I would be most grateful.

 

Thanks In Advance.

 

 

ssuede7ssuede7

OK, my problem was the Content-Length header.  You can see in my second post and typo'd the array key name.  I fixed that and gave it try and now everything is working great.  

 

My only issue now is that when I upload attachment the ContentType field is not populated with anything.  So when I download I am limited "application/force-download" for eveything.  Is there a proper way to manage ContentType in the upload and download process?

 

Thanks

 

Below is my code thus far:

require_once ($_SERVER["DOCUMENT_ROOT"].'/system/header_sforce.php'); $attid = $_REQUEST['attid']; $query = 'SELECT Id, ParentId, Name, BodyLength, Body FROM Attachment WHERE Id = \''.$attid.'\' '; $queryObject = $mySforceConnection->query($query); $file = $queryObject->records[0]->Body; $name = $queryObject->records[0]->Name; $length = $queryObject->records[0]->BodyLength; header('Content-Type: application/force-download'); header('Content-Disposition: inline; filename="'.$name.'"'); header('Content-Length: '.$length); if($file) echo $file;

 

 

 

 

 

This was selected as the best answer
gurumikegurumike
The Attachment object has a ContentType field, which you should be able to query and use in your script.
ClaiborneClaiborne

Remember that the body field is base-64 encoded. So you need a statement like

 

$file = base64_decode($result->records[0]->fields->Body);

ranjanikmca1.3940038284852163E12ranjanikmca1.3940038284852163E12

Hi,

Can any one give solution for this.

 $query1 = "Select body,ContentType,Name FROM Attachment Where Id = '00PQ0000001gQzc' OR Name='B.pdf' ORDER BY Name ASC " ;
 $queryResult = $partnerConnection->query($query1);
print_r($queryResult);
echo "<br/><Br/>";
print_r($queryResult->records);
echo "<br/><Br/>";
$records = $queryResult->records;

foreach ($queryResult->records as $record) {
    echo $record->fields->Name."<br/>\n";

}

In this above code  print_r($queryResult); displays only array[0] th record. But it shows [size] => 2.
I cant get the second record.

foreach ($queryResult->records as $record) {
    echo $record->fields->Name."<br/>\n";

}

displays only the 1st record name . It does not show the second record  Name.


The Result for the above code is

 

QueryResult Object ( [queryLocator] => 01gQ000000EhwCfIAJ-1 [done] => [records] => Array ( [0] => SObject Object ( [type] => Attachment [fields] => stdClass Object ( [Body] => NTQxRDQxNkRCNzY1Mj48MTMwMTAxMTRBMkM5NTk0MUE3MDU0MUQ0MTZEQjc2NTI+XSAvUHJldiA4MTA5MS9YUmVmU3RtIDgwODQ1Pj4NCnN0YXJ0eHJlZg0KODE0NjcNCiUlRU9G [ContentType] => application/pdf [Name] => A.pdf ) ) ) [size] => 2 )

Array ( [0] => SObject Object ( [type] => Attachment [fields] => stdClass Object ( [Body] => NTQxRDQxNkRCNzY1Mj48MTMwMTAxMTRBMkM5NTk0MUE3MDU0MUQ0MTZEQjc2NTI+XSAvUHJldiA4MTA5MS9YUmVmU3RtIDgwODQ1Pj4NCnN0YXJ0eHJlZg0KODE0NjcNCiUlRU9G [ContentType] => application/pdf [Name] => A.pdf ) ) )

A.pdf

 

If I remove the body from the query means it displays both records. //$query1 = "Select ContentType,Name FROM Attachment Where Id = '00PQ0000001gQzc' OR Name='B.pdf' ORDER BY Name ASC " ;

If I include body in the query means it displays only first record. //$query1 = "Select Body,ContentType,Name FROM Attachment Where Id = '00PQ0000001gQzc' OR Name='B.pdf' ORDER BY Name ASC " ;

Is anything wrong with Code ?

Rémi BERTHONRémi BERTHON
Hey, I was wondering if you managed to solve the problem for retrieving attachements. I am facing the same issue for the records array. Thank you