TUTORIAL (Part 1): Alternative to the SC provided file uploader1

Go to Part 2!!

Introduction

This is a bit of a mini tutorial for anyone who wants to use a third-party javascript / jquery file uploader instead of the “supplied” SC one (I guess until such time SC implement something better). Note: This tutorial is split into 2 posts as it was too large for a single post.

I did this with a third party uploader because the SC supplied uploader is somewhat prehistoric and inflexible, and the one implemented here isn’t, plus it’s a lot prettier and professional looking. NOTE: plupload requires your target audience’s browser to have Flash, Silverlight or HTML5 support to run, depending on the “widget” you are planning to use from their suite.

Now, this tutorial is very specific to a particular (free at this time) third-party javascript uploader called “plupload” running on SC v8. That said, I imagine the overall principle / approach is largely the same regardless of the uploader and / or version of SC.

I am no expert with plupload and this post just tells you what I did to get it to work in SC (for me). I am happy to answer some questions / clarify etc., but I am NOT the technical expert supporting this merging of technologies. I make no claims nor guarantees, and if you follow / try this I take no responsibility to any harm that may befall your applications.

This tutorial is offered as is and is posted here for anyone who may be interested in doing the same thing. It took me a long time to get it working how I wanted, so this is in the spirit of trying to alleviate some pain for others. I’m sure I’m not the only one to have done this either (and it may even be really obvious to you gurus out there). But when I went looking for help on this type of integration I didn’t really find anything, so I did it the hard way…

Finally, this solution is not necessarily the best, most secure, or only way to achieve this. I am well aware of that. That said, I’m happy to hear from people with efficiency / security thoughts or suggestions.

Getting Started

All you really need is the uploader javascript build. By all means check out their website for more details and demos etc (http://www.plupload.com) and to see what all the fuss is about (you can download it from there too).

The high-level steps to get this implemented are:
[LIST=1]

  • Get the uploader
  • Extract it
  • Create your own 'upload.php' script
  • Modify an SC app to use the uploader [/LIST]

    So - working our way through the steps:

    Step 1 - Get the uploader

    Download the uploader (get from the vendor’s website - www.plupload.com). This tutorial uses v2.1.2.

    Step 2 - Extract it

    NOTE: My development environment is Linux (Ubuntu 14.04). If you are Windows, for the paths I quote, find the equivalent Windows paths.

    If it’s zipped, extract the “js” folder (maintaining the folder structure) to:

    /opt/NetMake/v8/wwwroot/scriptcase/

    So that you end up with:

    /opt/NetMake/v8/wwwroot/scriptcase/js/

    Putting it there means that SC updates won’t remove it (found that one out the hard way - sigh).

    Step 3 - Create your own ‘upload.php’ script

    The plupload tool is basically a front-end interface. For the actual uploading it calls an upload PHP script which YOU define. It is in there that you do any security checks / restrictions etc (although some of the restrictions can be imposed via the call to plupload in your app’s PHP - I have some restrictions specified in both places, just to be sure, though it’s probably not necessary). Mine is below and will serve in most cases as is, or with a little tweaking.

    It addresses most security issues (I believe, but don’t hold me to that). In my case, I am allowing only PDF and image files to be uploaded (specifically - ‘jpg’,‘png’,and ‘gif’ files).

    Because there is not direct connection between javascript and PHP (the former being client-side, the latter server-side), the upload script also needs to provide a mechanism to capture the details of the file uploaded so SC can use it. I did this by creating and updating a “log” file (upload_log.txt) that SC can read.

    It’s only ever one line long and is “reset” before each upload - which suits my use, but you may need something different - particularly if multiple files are being uploaded. My use of plupload allows only one file to be uploaded at a time. That said, plupload handles multiple files quite happily, so if you want that you’ll need to tweak your upload script accordingly.

    So - here’s my “upload.php” script…

    <?php
    $file = 'upload_log.txt';
    
    if (file_exists($file)) {
    	unlink($file);			// Start off clean deleting old log file
    }
     
    if (empty($_FILES) || $_FILES["file"]["error"]) {
    	file_put_contents($file, "ERROR: No filenames parsed.
    ");
    	die('{"jsonrpc" : "2.0", "error" : {"code": 501, "message": "No filenames parsed"}, "details" : "Error description"}');
    }
    
    $fileName = trim($_FILES["file"]["name"]);
    
    if (file_exists('../file/doc/timesheets/' . $fileName)) {
    	file_put_contents($file, "ERROR: File already exists.
    ");
    	die('{"jsonrpc" : "2.0", "error" : {"code": 502, "message": "File already exists"}, "details" : "Error description"}');
    }
    
    $whitelist_ext = array('jpg','png','gif','pdf');
    $whitelist_type = array('image/jpeg', 'image/png', 'image/gif', 'application/pdf');
    
    $file_info = pathinfo($_FILES["file"]["name"]);
    $ext = strtolower($file_info['extension']);
    
    if (!in_array($ext, $whitelist_ext)) {
    	file_put_contents($file, "ERROR: Invalid file extension.
    ");
    	die('{"jsonrpc" : "2.0", "error" : {"code": 504, "message": "Invalid file extension"}, "details" : "Error description"}');
    }
    
    if (!in_array($_FILES["file"]["type"], $whitelist_type)) {
    	file_put_contents($file, "ERROR: Invalid file type.
    ");
    	die('{"jsonrpc" : "2.0", "error" : {"code": 505, "message": "Invalid file type"}, "details" : "Error description"}');
    } elseif ($_FILES["file"]["type"] <> 'application/pdf') {	// if not a PDF verify a proper image file
    	if (!getimagesize($_FILES["file"]["tmp_name"])) {
    		file_put_contents($file, "ERROR: File is not a valid image file.
    ");
    		die('{"jsonrpc" : "2.0", "error" : {"code": 506, "message": "File is not a valid image file"}, "details" : "Error description"}');
    	}
    }
    
    // If all tests pass, move the file to the correct dir and list the filename.
    
    // If PROD decomment line below
    move_uploaded_file($_FILES["file"]["tmp_name"], "../_lib/file/doc/timesheets/$fileName");
    
    // If DEV decomment line below
    //move_uploaded_file($_FILES["file"]["tmp_name"], "../file/doc/timesheets/$fileName");
    
    file_put_contents($file, $fileName);
    die('{"OK": 1}');
    ?>
    

    Once you have created it - put it in the root of the “js” folder you created earlier. This is also where the log file “upload_log.txt” will be created / updated.

    Go to Part 2!!

  • Great, tracked to future reading

    Hi,
    thanks for your contribution. I will give it a try because upload provide by SC has a problem when using it in an Android app (I mean viewed inside an Android app via a web browser).

    Thanks

    Sylvain

    Thanks for this code!. It’s fine!.