<

Go Premium for a chance to win a PS4. Enter to Win

x

Image ajax upload ,validate,rename,resize using Jquery & Coldfusion

Published on
12,803 Points
6,303 Views
Last Modified:
Hi.
There are several upload tutorials using jquery and coldfusion. I found a very interesting one here Upload Your Files using Jquery & ColdFusion and Preview them .
I did keep the main js functions but made several changes.
To understand the code you must be familiar with little of jquery and html/cfml file uploading. I'm using html 4 , jquery ajaxForm and CF 8 + for uploading , editing  and showing the images to the user without page refresh.

Changes to the main code from www.randhawaworld.com:
1. Add - delete "n" file inputs
2. Js filesize validation (not for IE < 10)
3. js extension validation
4. Using a cfc instead of cfm and use the advantage to return an array with "n" data
5. server side size and file validation using IsImageFile tag instead of using the accept attribute in the cffile action="upload" tag
6. renaming
7. resizing using the very interesting and useful ImageScaleToFitb tag.
8. returning an array with all needed values like totalerros,errormessages,uploaded totalsize, uploaded images a.s.o
9. Finally use these array to show messages and images using jquery.

In most browsers it is working fine except........Internet Explorer

There are some issues using this with IE. The progress bar is showing only 0% onuploading. IE 10 is showing 1%. Well i hope somebody could fix this.


I will be very happy you like.
I also would like to thank myselfrandhawa for his help.

Time to go to the interesting part ....the code:
First the html file including all the js code. The advantage is that the user can add so many file fields he wants to. Using js validation i'm checking filesize and file extension on formsubmit. The file size validation is not working in IE < 10. Don't worry. I'm validating the files after upload and return error messages if there are any using server side validation in my cfc.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax Upload with jQuery and ColdFusion</title>
<link href="style/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="Wrapper">
 <h1>Ajax Upload with jQuery and ColdFusion</h1>
 <p>Max. image size : 2 mb</p>
   <div id="finaloutput"></div>
   <div id="finalerroroutput"></div>
  <form action="" method="post" enctype="multipart/form-data" id="UploadForm">
   <div class='file_upload' id='f1'>
    <div id="preview_1" class="preview">
     <img id="thumb_1" width="90px" height="90px" src="no-image.gif" border="0">
    </div>
    <div id="counter_1" class="counter"><span>1</span></div>
    <div id="up_1" class="upload">
     <input name='attachment_1' type='file' id="attachment_1" class="filefield"/>
     <span id="info_1" class="info"></span>
    </div>
    <div class="clearboth"></div>
   </div>
   <div id='file_tools'>
    <img src='add-file-icon.png' id='add_file' title='Add new input'/>
    <img src='delete-icon.png' id='del_file' title='Delete' style="display:none;"/>
   </div>
   <div id="SubmitButtondiv" style="padding-left:120px;">
    <input type="submit"  id="SubmitButton" value="Upload" />
   </div>
    <cfset filecounter = 1 />
    <input type="hidden" name="filecounter" id="filecounter" value="<cfoutput>#filecounter#</cfoutput>">
  </form>
  <div id="newfileslink"><a href="<cfoutput>#CGI.SCRIPT_NAME#</cfoutput>">Add new images</a></div>
  <div id="progressbox">
   <div id="progressbar"></div>
   <div id="statustxt">0%</div>
  </div>
 </div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="js/jquery.form.js"></script>
<script>
$(document).ready(function () {
    var progressbox = $('#progressbox');
    var progressbar = $('#progressbar');
    var statustxt = $('#statustxt');
    var submitbutton = $("#SubmitButton");
    var myform = $("#UploadForm");
    var finaloutput = $("#finaloutput");
    var info = $('.info');
    var maxfilesize = 2;
    var maxfilesizeerror = 'Max upload filesize is 2 mb';
    var accept = 'gif|jpg|jpeg|png|bmp';
    var accepterror = 'Invalid file';
    var completed = '0%';
    var preview = $('.preview');
    $(myform).ajaxForm({
        dataType: 'json',
        url: 'processupload.cfc?method=fupload&returnformat=json',
        beforeSubmit: validate,
        beforeSend: function () { //brfore sending form
            submitbutton.attr('disabled', ''); // disable upload button
            statustxt.empty();
            progressbox.show(); //show progressbar
            progressbar.width(completed); //initial value 0% of progressbar
            statustxt.html(completed); //set status text
            statustxt.css('color', '#000'); //initial color of status text
            info.text('');
            finaloutput.text('');
            finaloutput.removeClass('error');
        },
        uploadProgress: function (event, position, total, percentComplete) { //on progress
            progressbar.width(percentComplete + '%') //update progressbar percent complete
            statustxt.html(percentComplete + '%'); //update status text
            if (percentComplete > 50) {
                statustxt.css('color', '#fff'); //change status text to white after 50%
            }
        },
        complete: function (response) { // on complete
            myform.resetForm(); // reset form
            submitbutton.removeAttr('disabled'); //enable submit button
            progressbox.hide(); // hide progressbar
            d = response.responseText;
            var d = $.parseJSON(d);
            if (jQuery.isArray(d) === true) {
                //The response is an array with one line. In js we start to count from 0
                //Using response[0]['attribute'] we get the array data
                var totalerrors = d[0]['totalerrors'];
                var images = d[0]['images'];
                var totalsize = d[0]['totalsize'];
                var uploadedfiles = d[0]['uploadedfiles'];
                var uploadedfiles = parseInt(uploadedfiles);
                //var cnt = 0; //uncomment this if you want to change the counter
                jQuery.each(images, function (index, value) {
                    var up = $('#up_' + index); //get the up div using the index
                    var pr = $('#preview_' + index); //get the preview div using the index
                    var cn = $('#counter_' + index); //get the counter div
                    if (value.match("^success")) { //If value strats with success
                        //cnt++ // add one to counter //uncomment this if you want to change the counter
                        var i = value.split("_"); //split value here "_"
                        var value = i[1]; //get the image file after "_"
                        pr.html('<img src="uploads/thumbs/' + value + '" alt="" width="90" height="90"/>');
                        //cn.html('<span>' + cnt + '</span>');//uncomment this if you want to change the counter
                        pr.removeClass('loading');
                        up.html('<span>Successfully upload</span>').addClass('success');
                    } else if (value.match("^false")) { //if value starts with false
                        var i = value.split("_"); //split value here "_"
                        var value = i[1]; //get the error message after "_"
                        pr.removeClass('loading');
                        up.html('<span>' + value + '</span>').addClass('error');
                        //cn.html('<span>' + cnt + '</span>');
                        $('#f' + index).delay(4000).slideUp('slow');
                    }
                });
                var fs = $("#finaloutput");
                fs.addClass('success').html('<span>' + uploadedfiles + ' files have been uploaded successfully.<br>Total upload filesize:' + totalsize + ' mb</span>');
                if (totalerrors > 0) {
                    var errors = d[0]['errors'];
                    if (jQuery.isArray(errors) === true) {
                        var fe = $("#finalerroroutput");
                        fe.addClass('error').html("<ul class='errorlist'  id='errorlist'></ul>");
                        var output = [];
                        jQuery.each(errors, function (index, value) {
                            output.push('<li>' + value + '</li>');
                        });
                        $('#errorlist').html(output.join(''));
                        fe.delay(4000).slideUp('slow');
                    }
                }
				$('#newfileslink').show();
            } else {
                var fe = $("#finalerroroutput");
                fe.addClass('error').text('There was an error. Please try later or contact with us.');
            };
        }
    }, "json");

    function validate(formData, jqForm, options) {
        var error = 0;
        var fileexists = 0;
        var info = $('.info');
        var output = $('#output');
        output.removeClass('error');
        output.text('');
        info.text(''); // delete all info
        $('.filefield', jqForm).each(function () {
            if ($(this).val()) {
                fileexists++
                var target = $(this).attr('id');
                var i = target.split("_");
                var id = i[1];
                var pid = $('#preview_' + id);
                var inf = $('#info_' + id);
                var aid = $('#attachment_' + id);
                pid.addClass('loading');
                if ($.browser.msie && $.browser.version < 10) { //file size validation except for Internet Explorer
                    //extension
                    var file = $(this).val();
                    var file = file.toLowerCase();
                    if (!eval('file.match(/(?:' + accept + ')$/)')) {
                        inf.show().text(accepterror); //show error
                        aid.val(''); // Delete value
                        pid.removeClass('loading');
                        error++
                        inf.delay(4000).slideUp('slow'); //remove error

                    }
                } else {
                    var myFile = document.getElementById(target);
                    var filesize = myFile.files[0].size;
                    var mbfilesize = filesize / (1024 * 1024);
                    //extension
                    var file = $(this).val();
                    var file = file.toLowerCase();
                    //extension validation
                    if (!eval('file.match(/(?:' + accept + ')$/)')) {
                        inf.show().text(accepterror); //show error
                        aid.val(''); // Delete value
                        pid.removeClass('loading');
                        error++
                        inf.delay(4000).slideUp('slow'); //remove error

                    }
                    //filesize validation
                    else if (mbfilesize > maxfilesize) {
                        inf.show().text(maxfilesizeerror);
                        aid.val(''); // Delete value
                        pid.removeClass('loading');
                        error++
                        inf.delay(4000).slideUp('slow'); //remove error
                    }
                }
            }
        });
        if (error) { //If error exists: stop the upload process
            $('.preview').removeClass('loading');
            return false;
        }
        if (!fileexists) { //if no file select 
            $('.preview').removeClass('loading');
            alert('Please select a file');
            return false;
        }
        $('#file_tools,#SubmitButtondiv').hide(); //hide buttons
        $('.filefield', jqForm).each(function () { //hide inputs without a file
            if (!$(this).val()) {
                var target = $(this).attr('id');
                var i = target.split("_");
                var id = i[1];
                var divtohide = $('#f' + id);
                divtohide.hide();
            }
        })
    }
    $('.filefield').live('change', function () { //validate onchange
        if ($(this).val()) {
            var target = $(this).attr('id');
            var i = target.split("_");
            var id = i[1];
			var aid = $('#attachment_' + id);
            var pid = $('#preview_' + id);
            var inf = $('#info_' + id);
            if ($.browser.msie && $.browser.version < 10) {
                //extension
                var file = $(this).val();
                var file = file.toLowerCase();
                //extension validation
                if (!eval('file.match(/(?:' + accept + ')$/)')) {
                    inf.show().text(accepterror); //show error
                    inf.delay(4000).slideUp('slow'); //remove error
					aid.delay(4000).val('');//remove file
                }
            } else { //file size validation except for Internet Explorer
                var myFile = document.getElementById(target);
                var filesize = myFile.files[0].size;
                var mbfilesize = filesize / (1024 * 1024);
                //extension
                var file = $(this).val();
                var file = file.toLowerCase();
                //extension validation
                if (!eval('file.match(/(?:' + accept + ')$/)')) {
                    inf.show().text(accepterror); //show error
                    inf.delay(4000).slideUp('slow'); //remove error
					aid.delay(4000).val('');//remove file
                }
                //filesize validation
                else if (!$.browser.msie && mbfilesize > maxfilesize) {
                    inf.show().text(maxfilesizeerror);//show error
                    inf.delay(4000).slideUp('slow'); //remove error
					aid.delay(4000).val('');//remove file
                }

            }


        }
    });
    //script to add - delete file field
    var counter = 2;
    $('img#add_file').click(function () {
        var tmpcounter = parseInt($('#filecounter').val());
        var newcounter = tmpcounter + 1;
        $('#filecounter').val(newcounter);
        $('#file_tools').before('<div class="file_upload" id="f' + counter + '"><div id="preview_' + counter + '" class="preview flleft inline"><img id="thumb_' + counter + '" width="90px" height="90px" src="no-image.gif" border="0"></div><div id="counter_' + counter + '" class="counter"><span>' + counter + '</span></div><div id="up_' + counter + '" class="upload"><input name="attachment_' + counter + '" id="attachment_' + counter + '" type="file" class="filefield"><span id="info_' + counter + '" class="info"></span></div><div class="clearboth"></div></div>');
        $('#del_file').fadeIn(0);
        counter++;
    });
    $('img#del_file').click(function () {
        var tmpcounter = parseInt($('#filecounter').val());
        var newcounter = tmpcounter - 1;
        $('#filecounter').val(newcounter);
        if (counter == 3) {
            $('#del_file').hide();
        }
        counter--;
        $('#f' + counter).remove();
    });
});
</script> 
</body>
</html>

Open in new window


The css: I'm sure that you can do it better than me!!
body {
width:100%;
font-family:Arial, Helvetica, sans-serif;
color:#666;
margin:0;
padding:0;
}

#Wrapper {
width:70%;
margin-right:auto;
margin-left:auto;
margin-top:50px;
background:#EEE;
border:1px solid #E6E6E6;
padding:20px;
}

#progressbox {
border:1px solid #09C;
position:relative;
width:400px;
border-radius:3px;
display:none;
text-align:left;
margin:10px;
padding:1px;
}

#progressbar {
height:20px;
border-radius:3px;
background-color:#033;
width:1%;
}

#statustxt {
top:3px;
left:50%;
position:absolute;
display:inline-block;
color:#000;
}
#newfileslink {
display:none;
padding-left:120px;
}
.clearboth {
clear:both;
}

.info {
line-height:30px;
font-family:Arial;
padding-top:5px;
color:red;
font-size:14px;
}

.success {
line-height:30px;
margin-bottom:10px;
background:#99f099;
border:1px solid #393;
padding:5px;
}

.error {
line-height:30px;
margin-bottom:10px;
background:#f0c6c3;
border:1px solid #c62;
}

div.preview {
display:inline;
float:left;
width:90px;
height:90px;
border:2px dotted #CCC;
}

div.preview.loading {
background:url(../loading.gif)no-repeat 39px 40px;
}

div.preview.loading img {
display:none;
}

#highlight {
margin-bottom:20px;
}

div.file_upload {
min-height:40px;
padding-bottom:5px;
}

#file_tools {
display:inline-block;
min-height:40px;
}

.counter {
display:inline;
float:left;
width:20px;
padding-left:5px;
}

div.counter,div.upload {
display:inline;
float:left;
}

div.upload .filefield,label {
display:block;
}

Open in new window


The cfc: The interesting server side part where i'm uploading - validating - renaming - copying - resizing images and final create the array with all the information that my jquery respond needs.
<cfcomponent>
 <cffunction name="init" output="false">
  <cfif not isdefined('application.maxsize')>
   <cfset variables.maxsize = 2464154 >
  <cfelse>
   <cfset variables.maxsize = application.maxsize >
  </cfif>
  <cfif not isdefined('application.bslash')>
   <cfset variables.bslash = '\'>
  <cfelse>
   <cfset variables.bslash = application.bslash>
  </cfif>
  <cfif not isdefined('application.thumbwidth')>
   <cfset variables.thumbwidth = 90 >
  <cfelse>
   <cfset variables.thumbwidth = application.thumbwidth>
  </cfif>
   <cfif not isdefined('application.thumbheight')>
   <cfset variables.thumbheight = 90 >
  <cfelse>
   <cfset variables.thumbheight = application.thumbheight>
  </cfif>
  <cfreturn this>
 </cffunction>
 <cffunction name="fupload" access="remote" returntype="array" returnformat="json">
  <cfargument name="filecounter" required="yes" default="1">
  <cfset var totalerrors = 0 />
  <cfset var errorlist = '' />
  <cfset var uploadedfiles = 0 />
  <cfset var totalsize = 0 />
  <cfset var next = true />
  <!--- RUN INIT FUNCTION --->
  <cfset init()>
  <!--- MAIN UPLOADS DIRECTORY --->
  <cfset var dir = "uploads">
  <cfset var destDir = ExpandPath("#dir#")>
  <cfif not directoryExists(destdir)>
   <cfdirectory action="create" directory="#destdir#">
  </cfif>
  <!--- THUMBS DIRECTORY --->
  <cfset var dirthumbs = "thumbs" />
  <cfset var thumDir = destdir & variables.bslash & dirthumbs />
  <cfif not directoryExists(thumDir)>
   <cfdirectory action="create" directory="#thumDir#">
  </cfif>
  <!--- LARGE IMAGE DIRECTORY --->
  <cfset var dirlarge = "large" />
  <cfset var largeDir = destdir & variables.bslash & dirlarge />
  <cfif not directoryExists(largeDir)>
   <cfdirectory action="create" directory="#largeDir#">
  </cfif>
  <!--- CREATE ARRAY TO CATCH A STRUCTURE WITH UPLOADED IMAGES--->
  <cfset var imgstruct = structnew()>
  <cfloop from="1" to="#arguments.filecounter#" index="i" step="1">
  <!--- BUILD DYNAMIC FILE FIELD (FORM FIELD KEY). --->
   <cfset var strField = "attachment_#i#" />
   <cfif (StructKeyExists( arguments, strField ) AND Len( arguments[ strField ] ))>
   <!--- WE CAN UPLOAD IMAGE FILE OUTSIDE OF THE ROOT FOLDER FOR MORE SECURITY, THAT'S WHY 
         I'M NOT UPLOADING THE IMG DIRECT INTO THE LARGE FOLDER --->
     <cffile action="upload" filefield="#strField#" destination="#destdir#" nameconflict="makeunique">
      <cfif IsImageFile("#destDir##variables.bslash##cffile.serverfile#")>
        <!--- DO SOMETHING. I'M RENAMING - RESIZING LATER --->
      <cfelse>
       <!--- DELETE FILE --->
       <cffile  action="delete"  file="#destDir##variables.bslash##cffile.serverfile#">
       <cfset var next = false />
      </cfif>
    <cfif next is false >
      <!--- SET FALSE IF THERE WAS  FILE ERROR.
	 YOU CAN USE THE ID OF THIS FILE IN THE JQUERY CODE TO SHOW THE ERROR  --->
     <cfset var errorlist = listappend(errorlist,"Image file " & i & " is not valid !","|")>
     <cfset var totalerrors = totalerrors + 1>
     <cfset var imgstruct[i] =  'false_Invalid file'  />
    <cfelse>
     <!--- CHECK THE MAX UPLOAD FILESIZE 
	   ( I HAVE NO VALIDATION FOR INTERNET EXPLORER ) --->
     <cfif cffile.Filesize GT variables.maxsize>
     <!--- CALCULATE IN MB TO SEND AN ERROR TEXT --->
      <cfset newimagemaxsize = variables.maxsize / (1024 * 1024)>
      <cfset newimagemaxsize = numberformat(newimagemaxsize,"0.00") />
      <!--- DELETE FILE --->
      <cffile  action="delete"  file="#destDir##variables.bslash##cffile.serverfile#">
      <!--- ADD ERROR TEXT --->
      <cfset var errorlist = listappend(errorlist,"Image file " & i & "extended max image size " & newimagemaxsize & " mb !","|")>
      <cfset var totalerrors = totalerrors + 1>
      <cfset var imgstruct[i] =  'false_Max upload size: ' & newimagemaxsize & ' mb' />
     <cfelse>
      <!--- CREATE A UNIQUE NAME TO RENAME THE UPLOADED IMAGE --->
      <cfset var token = createuuid()>
      <cfset var newname = token & '.' & file.clientfileext />
      <cfset var source = destDir & variables.bslash & cffile.serverfile>
      <cfset var newsrc = destDir & variables.bslash & newname >
      <!--- RENAME IMAGE. --->
      <cffile action="rename" source="#source#"  destination="#newsrc#">
      
      <cfimage source="#newsrc#" name="image">
      <!---  ANTIALISING IMAGE BEFORE COPYING--->
      <cfset ImageSetAntialiasing(image,"on")>
      <!--- COPY FILE IN THUMBS FOLDER --->
      <cffile action = "copy" 
               source="#newsrc#" 
               destination="#thumDir##variables.bslash##newname#" 
               nameconflict="makeunique">
      <!--- COPY FILE IN LARGE FOLDER --->
      <cffile action = "copy" 
               source="#newsrc#" 
               destination="#largeDir##variables.bslash##newname#" 
               nameconflict="makeunique">
       <!--- DELETE UPLOADED FILE  --->
       <cffile  action="delete"  file="#newsrc#">
       <!--- SOURCE IMAGE --->
       <cfset var sourceImage = thumDir & variables.bslash & newname>
       <cfset var img = imageRead(sourceImage)>
       <!--- RESIZE THUMB 
	        --->
       <cfif (img.width GT img.height OR img.width EQ img.height) AND img.width GT variables.thumbwidth>
        <cfset ImageScaleToFit(img,variables.thumbwidth,"","highestQuality")>
       <cfelseif img.height GT img.width  AND img.height GT variables.thumbheight>
        <cfset ImageScaleToFit(img,"",variables.thumbheight,"highestQuality")>
       </cfif>
       <cfset ImageWrite(img,"#thumDir##variables.bslash##newname#")>
       <!--- Image file to structure --->
       <cfset var imgstruct[i] =  'success_' & newname />
       <cfset var uploadedfiles = uploadedfiles + 1 />
       <cfset var totalsize = totalsize + cffile.Filesize />
     </cfif>
    </cfif>
   </cfif>
   <cfset var next = true />
  </cfloop>
  <!--- GET TOTAl SIZE AND CONVERT TO MB --->
  <cfset var totalsize = totalsize / (1024 * 1024)>
  <cfset var totalsize = numberformat(totalsize,"0.00") />
  <!--- CREATE ARRAY FOR ERRORS --->
  <cfset var errors = []>
  <cfloop list="#errorlist#" index="i" delimiters="|">
    <cfset arrayAppend(errors, i)>
  </cfloop>
  <cfset var finalarr = []>
  <cfset var datamain = {}>
  <!--- ADD ERRORLIST TO ARRAY --->
  <cfset datamain['errors'] = errors >
  <cfset arrayAppend(finalarr, datamain)>
  <!--- ADD ERRORS COUNT TO ARRAY --->
  <cfset datamain['totalerrors'] = totalerrors />
  <cfset arrayAppend(finalarr, datamain)>
  <!--- ADD UPLOADED IMAGES TO ARRAY --->
  <cfset datamain['images'] = imgstruct />
  <cfset arrayAppend(finalarr, datamain)>
  <!--- ADD TOTAL UPLOADED SIZE TO ARRAY --->
  <cfset datamain['totalsize'] = totalsize />
  <cfset arrayAppend(finalarr, datamain)>
  <!--- ADD UPLOADED FILES COUNT TO ARRAY --->
  <cfset datamain['uploadedfiles'] = uploadedfiles />
  <cfset arrayAppend(finalarr, datamain)>
  <cfreturn finalarr>
 </cffunction>
</cfcomponent>

Open in new window


Notice: You will need of course the jquery.form.js plugin

Attached all files
uploading.zip
0
Comment
Author:Panos
1 Comment
 
LVL 16

Expert Comment

by:Gurpreet Singh Randhawa
Great work @panosms, CF Community will be all thankful for this wonderful tutorial

Keep up the Good work
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Join & Write a Comment

Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month