Asynchronously upload file via Zoho Api

1.4k views Asked by At

I'm writing a web app that allows users to interface with the Zoho CRM, Zoho provides an api which I am using. They say the don't allow AJAX requests for security reasons, but i've found a workaround where I make an AJAX request to a php file that does a standard post using cURL and returns a value that I can get in my jQuery ajax "success" handler, that works just fine.

The issue i'm running into now is how to upload a file with the api using AJAX. My understanding of file io on the web is very limited and I think the gaps in my knowledge are preventing me from figuring this out. Being that it's not simple text and drop down inputs that i'm passing in my AJAX calls, but instead files, I'm having issues constructing a url for the request. The api says the parameter should be "FileInputStream", but i've only found that to exist in java. I'd like to keep everything in PHP/JS land. I don't really understand where the file data is once uploaded, and how the api works, does it need a file path? BLOB? something else?

Here's what I have so far (Main HTML/PHP)

<div class="info_card" id="main-search">
<form id="myid" action="https://crm.zoho.com/crm/private/xml/Potentials/uploadFile?authtoken=AUTHTOKEN&scope=crmapi&id=ID" enctype="multipart/form-data" method="post">
<input type="file" id="fileInput" name="fileInput">
<input type="text" name="foo" id="foo" value="foofoo">
<button type="button" name="submit" id="ajaxSubmit">upload</button>
</form>
</div>
<script type="text/javascript">
$(function () {
    $("#ajaxSubmit").click( function () {
        console.log('clicked:');
        var fd = new FormData();

        fd.append( "fileInput", $("#fileInput")[0].files[0]);
        fd.append("foo", $("foo"));
        $.ajax({
            url: 'ajaxUpload.php',
            type: 'POST',
            cache: false,
            data: fd,
            processData: false,
            contentType: false,
            beforeSend: function () {
                console.log(("Uploading, please wait...."));
            },
            success: function (data) {
                console.log(("Upload success."));
                console.log(data);
            },
            complete: function () {
                console.log(("upload complete."));
            },
            error: function () {
                alert("ERROR in upload");
            }
        });

    });
});
</script>

(The ajax handling php page)

<?php
require_once($_SERVER[DOCUMENT_ROOT]."/models/zohoFunctions.php");
$url = "https://crm.zoho.com/crm/private/json/Potentials/uploadFile";
$params = "authtoken=AUTHTOKEN&scope=crmapi&id=ID&content=";
$params .= "@".$_FILES['fileInput'];
echo $params."\n";
echo makeURLRequest($url, $params);
 ?>

(The function being called "makeURLRequest")

function makeURLRequest($url, $param){
  // Make the url request
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
  $result = curl_exec($ch);
  curl_close($ch);
  return $result;
}

The file upload works just fine if I use a form and set the action to the base url that is specified by zoho's api.

I've also hardcoded some urls in for debugging purposes, I hope the inclusion of all my code helps to show what i'm attempting to achieve.

The values for "authtoken" and "id" have been replaced for security reasons.

1

There are 1 answers

0
Eric Schirtzinger On

Thanks to @PatrickQ I was able to solve the problem,

By passing a CURLFile object in the post data field "content" I was able to get the api to be happy. On the ajax side of things I just created a FormData object and appended the fileInput to it. This way the ajax handling php file was able to use $_FILE superglobal to grab all the info it needed to construct the CURLFile object.


AJAX form submit

// Form setup
<form id="myid" action="ajaxUpload.php" enctype="multipart/form-data" method="post">
<input type="file" id="fileInput" name="fileInput">
<button type="submit" name="submit" id="formSubmit">upload</button>
</form>

// AJAX submit function
$(function () {
    $("#formSubmit").click( function (e) {
        e.preventDefault(); 
        console.log('clicked:');
        var fd = new FormData();
        fd.append( "fileInput", $("#fileInput")[0].files[0]);
        $.ajax({
            url: 'ajaxUpload.php',
            type: 'POST',
            cache: false,
            data: fd,
            processData: false,
            contentType: false,
            beforeSend: function () {
                console.log(("Uploading, please wait...."));
            },
            success: function (data) {
                console.log(("Upload success."));
                console.log(data);
            },
            complete: function () {
                console.log(("upload complete."));
            },
            error: function () {
                alert("ERROR in upload");
            }
        });
    });
});

AJAX action php file

<?php
$file = $_FILES['fileInput'];
// base url
$url = "https://crm.zoho.com/crm/private/xml/Potentials/uploadFile";
$ch = curl_init();
$cfile = new CURLFile($file['tmp_name'],$file['type'],$file['name']);
$param = array(
  'authtoken' => AUTHTOKEN,
  'scope' => "crmapi",
  'id' => ID,
  'content' => $cfile
);

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
?>