2

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.

Snow
  • 3,820
  • 3
  • 13
  • 39
  • Just so everyone knows, it was something to do with the headers. Here's the code that ended up solving the issue for me. – Paul Michael Jan 03 '20 at 06:28
  • btw you were lying with the headers actually. when you give CURLOPT_POSTFIELDS an array, curl will upload the file in the `Multipart/form-data` format, where the correct header looks like ```Content-Type: multipart/form-data; boundary=------------------------fe1569598bc62ae7``` - but instead you sent ```Content-Type: application/octet-stream```, telling the server you sent the file raw (and raw != multipart/form-data) – hanshenrik Jan 03 '20 at 22:38

2 Answers2

0

You didn't need to set headers like Content-Type: application/octet-stream or other to upload file. just need using curl_file_create method to send your file.

Your code must be some thing like this:

if (function_exists('curl_file_create')) { // for php 5.5+
    $File_Address = curl_file_create($file_name_with_full_path);
} else {
    $File_Address = '@' . realpath($file_name_with_full_path);
}

$post = array('file_name'=> $File_Address);
$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);

$result = curl_exec($ch);
ttrasn
  • 4,322
  • 4
  • 26
  • 43
  • Thanks for the reply, but no bueno. I no longer get the "=--------------------------a0fe4530540c659b " but I still get the content stuff in the CSV file. There has to be something else, I suppose – Paul Michael Dec 29 '19 at 07:16
  • @PaulMichael can you tell now what is in your file after upload? I think your source file has problem maybe! – ttrasn Dec 29 '19 at 07:45
  • My source file is absolutely not the problem. It's clean. Before I upload the file it has 30 rows of info, 2 columns. After I upload it, the 30 rows get pushed down and the first 2 rows are populated with Content-Disposition: form-data; name="file"; filename="/home/username/website/path/file.csv" Content-Type: application/octet-stream ------ As such, the file on the other end is being mangled somewhere in the stream. The far end is taking my entire request and making it a file. I just need it to accept the file, not include the headers. – Paul Michael Dec 29 '19 at 18:23
0

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);
  • Warning, this code will mess up binary data if the **uploader** is running on Windows. to get safe portable behavior that works on both Linux and Windows, change `$file = fopen($fLocation, 'r');` to `$file = fopen($fLocation, 'rb');` – hanshenrik Jan 03 '20 at 22:30