0

I am trying to send a POST request to an API and part of that request I am adding a CSV file to get return tokens based on the emails and numbers I provide. The first few lines of code use data that I retrieve from my database, and that as well as generating the file and populating it with text data is correct. The problem is with my cURL. When I make this request in PostMan, the result is perfectly fine, and I actually used the PHP-curl generated code from PostMan to write this request. However, the line

filename=\"".$filename."\"\r\n 

does not, for some reason, bring up the file that was just correctly populated before, and the API log says that the file has no data in it. Both files are located in the same directory, so I really am at a loss for what I'm doing incorrectly.

$file = fopen($filename, "w");

while ($row2 = mysqli_fetch_array($query2)){
    $txt = "$row2[email], $row2[firstname], $row2[lastname], 
    $row[company], $row2[mobilephone]\n";
    echo $txt;
    fwrite($file, $txt);
}

$curl = curl_init();

echo $filename."\n";

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://example.com",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\n
        Content-Disposition: form-data; 
        name=\"token\"\r\n\r\12345\r\n
        ------WebKitFormBoundary7MA4YWxkTrZu0gW\r\n
        Content-Disposition: form-data; name=\"datafile\";
        filename=\"".$filename."\"\r\n
        Content-Type: text/csv\r\n\r\n\r\n
        ------WebKitFormBoundary7MA4YWxkTrZu0gW--",
    CURLOPT_HTTPHEADER => array(
        "cache-control: no-cache",
        "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
    ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

if ($err) {
    echo "cURL Error #:" . $err;
} else {
    echo $response;
}

Can anyone spot what I am doing incorrectly here?

NOTE: I have replaced several fields and strings with dummy data for privacy/security reasons

Jodo1992
  • 745
  • 2
  • 10
  • 32

2 Answers2

1

API log says that the file has no data in it

The reason is that you TELL that you will send "filename.txt" in your query, but not actually SEND data.

For example, if you send filename.txt with ||test|| content with POST query, the result query will be like this:

------WebKitFormBoundaryWJ0Ly0MV6I2Kvqwe
Content-Disposition: form-data; name="token"

12345
------WebKitFormBoundaryWJ0Ly0MV6I2Kvqwe
Content-Disposition: form-data; name="datafile"; filename="filename.txt"
Content-Type: text/plain

||test||
------WebKitFormBoundaryWJ0Ly0MV6I2Kvqwe--

As you see, content of the file should be added to the query. In your query there is only declaration, that file with $filename name will be sent and its content will be later, but no content at all:

------WebKitFormBoundary7MA4YWxkTrZu0gW\r\n
        Content-Disposition: form-data; name=\"datafile\";
        filename=\"".$filename."\"\r\n
        Content-Type: text/csv\r\n\r\n\r\n

So server will answer that file is empty.

If you want to send file, you CAN add content later (as in my example), but it is bad approach. According to documentation you should use another techniques to send file data. Send array with variable filename with either path to the file prefixed with @ or use CURLFile (like here)

SeRRgIO
  • 167
  • 2
  • 12
  • It is being sent as form data instead of just a pure file. That's why postman generates it this way. The problem is the `$filename` comes across to the API as blank when it is populated beforehand – Jodo1992 Jul 11 '17 at 18:01
  • Thorough explanation. I wasn't aware the data had to be separately notified to the server – Jodo1992 Jul 11 '17 at 18:38
1

i can't think of ANY (sane) reason to do the multipart/form-data-encoding manually, when its trivial to make curl encode it for you. that whole curl_setopt_array can be replaced with

curl_setopt_array ( $curl, array (
        CURLOPT_URL => "https://example.com",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_POST=>true,
        CURLOPT_POSTFIELDS => array (
                'token' => '12345',
                'datafile' => new CURLFile ( $filename, 'text/csv', 'datafile' ) 
        ),
        CURLOPT_HTTPHEADER => array (
                "cache-control: no-cache" 
        ) 
) );
  • and curl will do the multipart/form-data encoding for you.
hanshenrik
  • 19,904
  • 4
  • 43
  • 89