Search code examples
phpcurlcontent-typezendeskzendesk-api

When uploading a file with cURL the file gets modified with header information


When uploading a file using cURL, I'm finding the file on the remote side is getting modified and header information gets dumped into the file. I suspect this is something in my header info, but I'm lost beyond that. I'm trying nearly anything.

Here's the code I'm using.

$fLocation = realpath('file.csv');  
$finfo = finfo_open(FILEINFO_MIME_TYPE);  
$fType = finfo_file($finfo, $fLocation);  
finfo_close($finfo);      
$cFile = curl_file_create($fLocation);  
$post = array('file'=> $cFile);  
$ch = curl_init();  
curl_setopt($ch, CURLOPT_URL, $url);  
curl_setopt($ch, CURLOPT_POST,1);  
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);  
curl_setopt($ch, CURLOPT_USERPWD, $username.":".$password);  
curl_setopt($ch, CURLOPT_HTTPHEADER, "Content-Type: application/octet-stream");  
$result = curl_exec($ch);  

I've tried a handful of different Content-Types for the header, from application/binary, to multipart/form-data and not even sending content-type at all in the headers. I suspect I need to add something more to the headers.

Anyways, the file I'm sending is a .csv, but I WANT to send a .xlsx file in the end (I'm using the .csv to test). When I get the file from the remote server, and open it in a text editor, I see there's info added to the start and end of the file, with the file's original data in between. Here's what gets added to the top.

=--------------------------a0fe4530540c659b  
Content-Disposition: form-data; name="file"; filename="/home/username/website/path/file.csv"  
Content-Type: application/octet-stream 

And, the bottom

--------------------------a0fe4530540c659b--

Essentially, I figured this out when all my .xlsx files were corrupt once they got to the other side. I changed what I was sending to a plain text file (CSV) and that's when I realized what was going on.

Here's more interesting information. It's actually me sending something to ZenDesk via their APIs, and I'm obviously doing this in PHP using cURL. When I get the JSON reply from Zendesk, part of it looks like this...

[file_name] => file.csv  
[content_url] => https://org.zendesk.com/attachments/token/jdjdjdjdjdjhdjdjdj/?name=file.csv  
[content_type] => multipart/form-data  
[size] => 5615  

What's interesting about that, is it's seeing what I've uploaded to be multipart/form-data. This remains true even when I change the Content-Type in the header.

Surely I'm missing something stupid and easy here.


Solution

  • Just so everyone knows, it was something to do with the headers. Here's the code that ended up solving the issue for me.

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_MAXREDIRS, 10 );
    curl_setopt($ch, CURLOPT_URL, $json_url);
    curl_setopt($ch, CURLOPT_USERPWD, $username.":".$password);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/binary'));
    curl_setopt($ch, CURLOPT_POST, true);
    $file = fopen($fLocation, 'r');
    $size = filesize($fLocation);
    $fildata = fread($file,$size);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fildata);
    curl_setopt($ch, CURLOPT_INFILE, $file);
    curl_setopt($ch, CURLOPT_INFILESIZE, $size);
    curl_setopt($ch, CURLOPT_USERAGENT, "MozillaXYZ/1.0");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    $result = curl_exec($ch);