jqueryajaxcoldfusioncffile

Upload multiple files with jquery and coldfusion cffile


Not really a question... Just wanted to post this somewhere because I couldnt find it elsewhere. Now that I've cobbled together a working demo I thought i would share. This works equally well on Coldfusion and Railo CFML servers.

The problem is that for CFML developers is that CFFILE doesn't work with <input type="file" multiple> ... traditionally if you wanted to upload 3 files and use CFFILE on the back end you would have to include 3 separate file inputs on your calling page.

Here is my solution shaved down for simplicity. It uses Jquery $.ajax to make several calls to CFFILE and returns the results to a div on the calling page. Im sure there is a better way to do this and my code is probably a complete hack but the below example works. Hope this helps someone.

multiFileUpload.cfm

<!DOCTYPE html>
<CFPARAM Name="URL.contractID" defualt="">
<head>
<title>Multi File Upload</title>
<script>
$( document ).ready(function() {
       $('#submitFrm').on("click", function(e){
        e.preventDefault();

            //The jquery.each() statement loops through all the files selected by user
    $.each($('#multiFile')[0].files, function(i, file) {
           var data = new FormData(); 
               data.append('file-0', file);
           ajaxUpload(data);
            }); //end .each statement       

        }); //end submitFrm's click function 

        function ajaxUpload(data){
        console.log("ajaxUpload function called");
        $.ajax({url: "multiFileUploadAction.cfm",
        data: data,
        cache: false,
        contentType: false, //this is need for this to work with coldfusion
        processData: false, //this is need for this to work with coldfusion
        type: 'POST',
        success: function(returnData){
             console.log(returnData);
                             //here is where you would update your calling
                             //page if successfull 
                             $("#msgDiv").html($("#msgDiv").html() + "<p>" + returnData + "</p>");
             },
        error: function(returnData){
               console.log(returnData);
               }
    }); //end .ajax call
    } //end ajaxUpload function
}); //end onDocument ready
</script>
<style>

</style>
</head>
<body>
<form action="multiFileUploadAction.cfm" Method="POST" enctype="multipart/form-data" class="well" id="multiFileFrm">
 <input type="file" name="multiFile" id="multiFile" multiple />
 <button class="btn btn-primary" id="submitFrm" >Submit</button>
 <cfoutput>
     <input type="hidden" Name="contractID" id="contractID" value="#URL.contractID#">  
 </cfoutput>
</form>
<div id="msgDiv" style="display:none;"></div>
</body>
</html>

This is my proccessing page... again stripped down to the bare minimum: multiFileUploadAction.cfm

<CFOUTPUT>
<CFTRY>
<cffile action="upload" 
            filefield="file-0" 
            destination="#expandpath("\images")#" 
            nameConflict="makeUnique">
    <cfcatch>
    #cfcatch.Message#
</cfcatch>
</cftry>
    <cfcontent reset="true" />Uploaded #cffile.serverFile#
</CFOUTPUT>
<!---
<cfdump var="#form#">
--->

Thats it... in my production code i create a JSON response that includes the saved file name and path to the file (because of the 'makeUnique' it could be different then what was sent) I also process the file to create a thumbnail and send it's name and path back to the calling page. That way on the calling page I can display a thumbnail. Hope someone finds this helpful.


Solution

  • Here's my solution to a similar issue another user had, which I resolved still utilizing the HTML5 "multiple" attribute for file uploads. You can still upload the form as you normally would, which would POST multiple files to the server. Rather than using CF's file upload utilities, you can simply loop over the form data and do the individual writes yourself, giving you full server-side control of the file details in a single request.

    ColdFusion handling of HTML5 <input type="file" multiple="multiple" />