2

I am wanting to send a file via http POST using PHP and cURL.

The form POST was working ok with basic fields besides the file being posted with 'application/json'. This needs to be multipart/form from what I understand.

Error I am getting is Notice: Array to string conversion on line
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

If anyone can help that would be great!

PHP

$orgID = (is_numeric($_POST['orgID']) ? (int)$_POST['orgID'] : 0);
$noteTitle = (isset($_POST['noteTitle']) ? $_POST['noteTitle'] : null);
$noteBody = (isset($_POST['noteBody']) ? $_POST['noteBody'] : null);

if(isset($_FILES['file']['tmp_name'])){

    $ch = curl_init();
    $cfile = new CURLFILE($_FILES['file']['tmp_name'], $_FILES['file']['type'], $_FILES['file']['name']);
    $data = array();                

    $data["TITLE"] = "$noteTitle";
    $data["BODY"] = "$noteBody";
    $data["LINK_SUBJECT_ID"] = "$orgID";
    $data["LINK_SUBJECT_TYPE"] = "Organisation";        
    $data['FILE_ATTACHMENTS']['FILE_NAME'] = $_FILES['file']['name'];
    $data['FILE_ATTACHMENTS']['CONTENT_TYPE'] = $_FILES['file']['type'];
    $data['FILE_ATTACHMENTS']['URL'] = $_FILES['file']['tmp_name'];

    $localFile = $_FILES['file']['tmp_name'];
    $fp = fopen($localFile, 'r');       

    $headers = array(
        "authorization: Basic xxx",
        "cache-control: no-cache",
        "content-type: multipart/form-data",
        "postman-token: xxx"
    );

    curl_setopt($ch, CURLOPT_URL, "https://api.insight.ly/v2.1/Notes");
    curl_setopt($ch, CURLOPT_UPLOAD, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
    curl_setopt($ch, CURLOPT_INFILE, $fp);
    curl_setopt($ch, CURLOPT_NOPROGRESS,false); 
    curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
    curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    $response = curl_exec($ch);

    if ($response === true) {
        $msg = 'File uploaded successfully.';    
    }
    else {
        $msg = curl_error($ch);         
    }

    curl_close ($ch);

    $return = array('msg' => $msg);

    echo json_encode($return);
}

HTML

<form method="POST" action="formSend.php" enctype="multipart/form-data">
    <input type="text" value="" name="orgID">
    <input type="text" value="" name="noteTitle">
    <input type="text" value="" name="noteBody">  
    <input name="file" type="file" id="file"/>
    <input type="submit" value="Submit" name="btnUpload"/>
</form>

4 Answers 4

2

Hi I have figured out the problem.

My params were not set correct on the api endpoint. Need to set a note_id(c_id)

But issue I am having now is posting all data at once. I am posting file after the note has been created thus generating the note id for me for posting file. Can anyone help with that? I can post a new question.

See updated code below:

//$orgID = (is_numeric($_POST['orgID']) ? (int)$_POST['orgID'] : 0);
//$noteTitle = (isset($_POST['noteTitle']) ? $_POST['noteTitle'] : null);
//$noteBody = (isset($_POST['noteBody']) ? $_POST['noteBody'] : null);

$noteID = (isset($_POST['noteID']) ? $_POST['noteID'] : null);

$localFile = $_FILES['file']['tmp_name'];
$fp = fopen($localFile, 'r');

$curl = curl_init();

$cfile = new CURLFILE($_FILES['file']['tmp_name'], $_FILES['file']['type'], $_FILES['file']['name']);
$data = array();                
//$data["TITLE"] = "$noteTitle";
//$data["BODY"] = "$noteBody";
//$data["LINK_SUBJECT_ID"] = "$orgID";
//$data["LINK_SUBJECT_TYPE"] = "Organisation";        
$data['FILE_ATTACHMENTS'] = $cfile;

curl_setopt_array($curl, array(
  CURLOPT_UPLOAD => 1,
  CURLOPT_INFILE => $fp,
  CURLOPT_NOPROGRESS => false, 
  CURLOPT_BUFFERSIZE => 128,
  CURLOPT_INFILESIZE => filesize($localFile),
  CURLOPT_URL => "https://api.insight.ly/v2.1/Notes/?c_id=" . $noteID . "&filename=" . $_FILES['file']['name'],
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $data,      
  CURLOPT_HTTPHEADER => array(
    "authorization: Basic xxx",
    "cache-control: no-cache",
    "content-type: multipart/form-data",
    "postman-token: xxx"
  ),
));
$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

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

HTML

<form method="POST" action="formSend.php" enctype="multipart/form-data">
    //<input type="text" value="" name="orgID">
    //<input type="text" value="" name="noteTitle">
    //<input type="text" value="" name="noteBody"> 
    <input type="text" value="" name="noteID">
    <input name="file" type="file" id="file"/>
    <input type="submit" value="Submit" name="btnUpload"/>
</form>

If anyone is interested this is my solution for using fpdf to generate a PDF document from the web form then auto send, instead of the file upload. FPDF file ---> send via CURL automatically NOT with file upload

Sign up to request clarification or add additional context in comments.

Comments

1

You need to build query string for data to be posted. Use http_build_query

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

5 Comments

Hi mate, thanks for the response, this does not work though.
Did you get any other error after using http_build_query?
There was this message $msg = 'File uploaded successfully.'; However theres nothing showing inside of the CRM (where contents/file is posting to). I usually expect a json string back with the response data ?
ok so http_build_query fixed the error Notice: Array to string conversion. This means curl executed successfully. You now have to debug the page you are posting to. First thing would be to see if post values are retrieved properly by printing $_POST.
I am not sure what you mean by debugging the page I am posting to? Do you mean api.insight.ly/v2.1/Notes ? I cannot access this page its part of a Saas CRM system
1

One omission I see is that you need to add your $cfile object to the $data array. This, coupled with the answer by Samir, should get you all squared away.

2 Comments

Hi thanks for picking that out. I am not sure where I should be putting this though? Does it have to match the API structure for POSTing? i.e ` $data['FILE_ATTACHMENTS']['FILE_NAME'] = $cfile; $data['FILE_ATTACHMENTS']['CONTENT_TYPE'] = $_FILES['file']['type']; $data['FILE_ATTACHMENTS']['URL'] = $cfile;
You should be able to just assign it like $data['imageFile'] = $cfile; similarly to how you specified $data['TITLE'] etc. Here's a Youtube video that walks through the process: youtube.com/watch?v=Od-LD9PwsaY
0

This all gets very confusing and "contradictory" very quickly! Because cUrl is quite flexible and powerful, little differences in usage context have a massive impact and can lead to DAYS of non-existent bug chasing.

Secondly, the URL/Endpoint you are posting to can also have it own "implementation" and expectations. This understanding it complicated when experience is only with GET requests AND the assumption/expectation is based of PHP Super Easy $_REQUEST

In the case above, simplifying: This is a live working example, but the postfields ($post) has been reduced from the 50 odd in use to a few for example. This will post as multipart form data.

Here important options are the options to use CURLOPT_POST and CURLOPT_POSTFIELDS and NOT CURLOPT_CUSTOMREQUEST. Doing so will require you to take care of required headers and in particular, content size header, etc.

// Post "field" array. Notice its 1 Dimensional. Else, this should rather accept JSON. simply decode array to json and proceed). Depends what server is expecting - Form data, Form + files, json or maybe just a RAW request body.
$post = array(  
            'RsmMaster1_TSM' => $tsm,
            '__EVENTTARGET' => '__Page',
            '__EVENTARGUMENT' => 'ExcelExport',
            '__VIEWSTATE'  => $viewstate,
            '__VIEWSTATEGENERATOR'  => $viewstategenerator,
            '__EVENTVALIDATION'  => $eventvalidation
 );

// Optional, Required in THIS case because, well gosh darn who knows, as the receiving server admin?
$headers = array(   
                'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language: en-ZA,en-GB;q=0.8,en-US;q=0.5,en;q=0.3',
                'Referer: https://example.com/Main.aspx'  
            );

// cUrl it into the goal!
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://example.com/Main.aspx');
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);                                                                  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7");
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');                                                                   
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);    
curl_setopt($ch, CURLOPT_HEADER, 0);
// curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); // Session maintain!
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FAILONERROR,    TRUE   );
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE  );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE  );

$content = curl_exec($ch);
curl_close($ch);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.