-2

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.

  • Take a look here first: https://stackoverflow.com/questions/5392344/sending-multipart-formdata-with-jquery-ajax . I was wondering if "contentType: false" could be the problem. Maybe $("#fileInput")[0].files[0] is also a problem. See how they handle it. I once had a working example similar to the "older browsers" solution – Emmanuel Delay Aug 29 '17 at 16:50
  • Hey thanks, I was able to get FormData working, so I got the $_FILE data passed from my Main page to the Ajax handling page. But the issue I was running into is submitting that data (file data) in an api call. The api says the parameter should be "FileInputStream", but everytime I try to construct a request URL my parameter is invalid. I guess I don't understand what should be passed in the request url. [API_documentation](https://www.zoho.com/crm/help/api/uploadfile.html) – Eric Schirtzinger Aug 29 '17 at 17:42
  • You probably want `"@".$_FILES['fileInput']['tmp_name']`. Alternatively, you could try sending a [CURLFile](http://php.net/manual/en/curlfile.construct.php) object. – Patrick Q Aug 29 '17 at 18:23
  • @PatrickQ I don't think the 'tmp_name' will work because the api calls for fileinputstream. I'm getting an error when I try it. It seems like CURLFile object is a step in the right direction. However I'm getting an internal server error when trying to append the CURLFile object to the parameter string (makes sense, it's an object that's probably not auto converted to a string). I just don't know how to send post data that's not a string. I've been dealing with only text inputs so far. – Eric Schirtzinger Aug 29 '17 at 19:58
  • Follow the example in the documentation that I linked. Create `$params` as an array, not a string. Also, note that `$_FILES['fileInput']` isn't a file stream either, it's an array. – Patrick Q Aug 29 '17 at 20:21

1 Answers1

-2

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;
?>