public
Last active

ColdFusion code for Plupload file uploading including chunked transfers

  • Download Gist
upload.cfc
ColdFusion
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
<cfcomponent>
 
<cffunction name="upload" access="remote" returntype="struct" returnformat="json" output="false">
<cfscript>
var uploadDir = expandPath('.') & '/uploads/'; // should be a temp directory that you clear periodically to flush orphaned files
var uploadFile = uploadDir & arguments.NAME;
var response = {'result' = arguments.NAME, 'id' = 0};
var result = {};
// if chunked append chunk number to filename for reassembly
if (structKeyExists(arguments, 'CHUNKS')){
uploadFile = uploadFile & '.' & arguments.CHUNK;
response.id = arguments.CHUNK;
}
</cfscript>
<!--- save file data from multi-part form.FILE --->
<cffile action="upload" result="result" filefield="FILE" destination="#uploadFile#" nameconflict="overwrite"/>
<cfscript>
// Example: you can return uploaded file data to client
response['size'] = result.fileSize;
response['type'] = result.contentType;
response['saved'] = result.fileWasSaved;
// reassemble chunked file
if (structKeyExists(arguments, 'CHUNKS') && arguments.CHUNK + 1 == arguments.CHUNKS){
try {
var uploadFile = uploadDir & arguments.NAME; // file name for reassembled file - if using a temp directory then this should be the final output path/file
if (fileExists(uploadFile)){
fileDelete(uploadFile); // delete otherwise append will add chunks to an existing file
}
 
var tempFile = fileOpen(uploadFile,'append');
for (var i = 0; i < arguments.CHUNKS; i++) {
var chunk = fileReadBinary('#uploadDir#/#arguments.NAME#.#i#');
fileDelete('#uploadDir#/#arguments.NAME#.#i#');
fileWrite(tempFile, chunk);
}
fileClose(tempFile);
}
catch(any err){
// clean up chunks for incomplete upload
var d = directoryList(uploadDir,false,'name');
if (arrayLen(d) != 0){
for (var i = 1; i <= arrayLen(d); i++){
if (listFirst(d[i]) == arguments.NAME && val(listLast(d[i])) != 0){
fileDelete('#uploadDir##d[i]#');
}
}
}
 
// you could add more error handling and return info from err
response = {'error' = {'code' = 500, 'message' = 'Internal Server Error'}, 'id' = 0};
}
}
return response;
</cfscript>
</cffunction>
 
</cfcomponent>

How are you posting to this CFC, or what are you setting the plupload URL to?

Thanks,
Ryan

var uploader = new plupload.Uploader({
...
url : 'upload.cfc?method=upload'
...
});

I am not sure a CFC really makes sense - may as well be a .cfm template since its working with data in the request but it does not really matter.

With CFC you could add other methods to flush temp dir etc.

In Coldufsion 8 ( https://gist.github.com/3839076 ) the uploaded file names are changing to last chunk (?) filename. For example: p178o71s3f11ubvl5154r61ds97.jpg .
How can we have the uploaded filenames be the same as the source filenames?

Ignore previous comment. FYI the problem was the option "unique_names : true" of plupload and not the cf code!

This is a life saver but I am having some issues:

  1. How do you get the file names into the database
  2. When changing nameconflict="overwrite" to nameconflict="makeunique" it doesn't work (I have made unique_names : false in the JS!

Cheers

Jan

I also would like to know how to get the file name for the makeunique. I need to upload the files using the cfm but somehow get the final uploaded file name back from the cfm and put into the form fields that plupload makes.

@PegWeb @jansolo1011

Plupload runs a callback named "FileUploaded" when the file is completely finished uploading. I suggest putting an ajax request in this callback to a cfml function that updates the table with the final filename.

Ex:

    $("#uploader").pluploadQueue({
    .....

    init : {    
        FileUploaded: function(up, file, info) {

            $.ajax({
                type: "POST",
                url: "upload.cfc?method=finished",
                data: { fileid: file.id },
                success: function() {
                    // Success
                }
            });
        }
    }

    .....
    });

I'm having issues getting the json messages in the cfreturn statement to display on the page with the pluploader.

                $(document).ready(function() {
                    $("##pluploader").pluploadQueue({       
                            runtimes : 'html5',
                            url : 'photosMultiUpload.cfc?method=upload',
                            max_file_size : '7mb',
                            chunk_size : '1mb',
                            unique_names : true,
                            dragdrop : true,
                            filters : [
                                    {title : "Image files", extensions : "jpg,gif,png,jpeg"}
                            ],
                            FilesAdded: function(editor,files){
                                alert(files);
                            }
                        ,Error: function(up, err) {
                            alert(err);
                        } 
                    ,FileUploaded: function(up, file, info) {
                        alert(file);
                    }
                });       
                });

I have the cftry/cfcatch as in your example. The uploader page displays a green tick and 100% uploaded and the firebug shows my json message:
error
Object { message="Internal Server Error", code=500}

message
"Internal Server Error"

code
500

Any advice?

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.