Using Dropzone.js
Single File Upload
<h2>Single File Upload</h2>
<div class="col-xs-4">
    <h4>Product Name</h4>
    <input id="product-name" class="form-control" placeholder="Product Name" 
         value="" onchange="setTargetFilename()">
    <br/>
    <h4>Target Language</h4>
    <select id="catalog-lang" class="form-control" onchange='setTargetFilename();'>
      <option value="en" selected>English (en)</option>
      <option value="es">Spanish (es)</option>
    </select>
</div>
<div class="col-xs-4">
    <h4>Supported Styles</h4>
    <select id="product-styles" name="product-styles" class="form-control" 
            size="15" multiple onchange="setTargetFilename()">
        <option value="Standard">Standard</option>
        <option value="Open">Open</option>
        <option value="Closed">Closed</option>
    </select>
    Use <kbd>ctrl</kbd> + <kbd>click</kbd> to select multiple.
</div>
<p/>
<div class="col-xs-4">
    <h4>Drop Zone</h4>
    <form id="dropzone1" action="upload.php" class="dropzone">
        <!-- Submit as $_POST any hidden fields as well -->
        <input type="hidden" id="target-file-name" name="target-file-name">
        <div class="fallback">
            <input name="file" type="file" class="form-control" />
            <input type="submit" value="Upload File" />
        </div>
    </form>
</div>
...
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="./lib/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="./lib/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="./lib/ie10-viewport-bug-workaround.js"></script>
 
<!-- Add Dropzone support -->
<link href="css/dropzone.css" type="text/css" rel="stylesheet" /> 
<script src="lib/dropzone.js"></script>
<script src="dropzone-options.js"></script>
<script>
  $(function() {
      setTargetFilename();
  });
 
  function setTargetFilename()
  {
      var arrStyles = [];
      $('#product-styles option:selected').each(function(i, selected) {
          arrStyles[i] = $(selected).val();
      });
      var styles = arrStyles.join("-");
      var targetFilename = $("#product-name").val() + "-" + styles + "-" + $("#catalog-lang option:selected").val();
 
      $("#target-file-name").val(targetFilename);
      console.log("Updated target filename: " + targetFilename );
  }
</script> 
file dropzone.options.js
//-----------------------------------------------------------------
// Dropzone options
//-----------------------------------------------------------------
 
//# Prevent Dropzone from auto discovering this element. This is useful 
//# when you want to create the Dropzone programmatically later.
//Dropzone.options.myDropzone = false;
//
//# Disable auto discover for all elements:
//Dropzone.autoDiscover = false;
 
//# "myAwesomeDropzone" is the camelized version of the HTML element's ID
//# Eg: Dropzone.options.myAwesomeDropzone = { ... }
 
Dropzone.options.dropzone1 = {
  url: "upload.php",     // Set the target url
  paramName: "file",     // The name that will be used to transfer the file
  maxFilesize: 2,        // MB
  thumbnailWidth:  80,
  thumbnailHeight: 80,
  parallelUploads: 20,
  dictDefaultMessage: "Drop files here or click to upload",
  previewTemplate: previewTemplate,
  //previewTemplate: document.querySelector('#preview-template').innerHTML,
  //autoQueue: false,                 // Make sure the files aren't queued until manually added
  //previewsContainer: "#previews",   // Define the container to display the previews
  //clickable: ".fileinput-button",   // Define the element that should be used as click trigger to select files.
  accept: function(file, done) {
    var errMsg = validateTargetFilename(file.name);
    if (errMsg.length > 0) {
        done(errMsg);
        console.log(errMsg);
        $("#cmd-status").html('<div class="alert alert-danger" role="alert">'+errMsg+'</div>');
    } else  if (file.name.indexOf(" ") > -1) {    // check whether filename has spaces
        file.name = file.name.replace(" ", "_");  // we get rid of spaces to avoid errors
        console.log("File name has spaces: [" + file.name +"]. It needs to be cleaned up.");
        //done("Invalid target file name for [" + file.name + "].  \nCannot upload file.  \n\nFile name contains spaces.");
        done();
        $("#cmd-status").html('<div class="alert alert-success" role="alert">Success uploading '+file.name+'</div>');
    } else { 
        done();
        $("#cmd-status").html('<div class="alert alert-success" role="alert">Success uploading '+file.name+'</div>');
    }
  },
  init: function() {
    this.on("addedfile", function(file) { 
        var errMsg = validateTargetFilename(file.name);
        if (errMsg.length > 0) {
            //alert(errMsg);
            //$("#dlg-title").html("File Upload");
            //$("#dlg-body").html(errMsg);
            //$("#dlg").modal('show');
        }
        console.log("Added file: targetname [" + file.name + "], " + 
            "name [" + file.name + "], type [" + file.type + "], size [" + file.size + "]"
        );
    });
  }
};
Multiple File Upload (Multiple Selection)
<div class="col-xs-12">
    <h2>Multiple File Upload Drop Zone</h2>
    Files are uploaded as-is.  No file renaming.  Use responsibly.
    <form id="dropzone2" action="upload.php" class="dropzone">
      <div class="fallback">
        <input name="file" type="file" multiple />
      </div>
    </form>
</div>
 
...
 
<!-- Add Dropzone support -->
<link href="css/dropzone.css" type="text/css" rel="stylesheet" /> 
<script src="lib/dropzone.js"></script>
Multiple File Upload (Individual Selection)
<div class="col-xs-12">
    <h2>Multiple File Upload (Individual Selection) Drop Zone</h2>
    <form id="dropzone3" action="upload.php"></form>
    <div id="actions" class="row">
      <div class="col-lg-7">
        <!-- The fileinput-button span is used to style the file input field as button -->
        <span class="btn btn-success fileinput-button">
            <i class="glyphicon glyphicon-plus"></i>
            <span>Add files...</span>
        </span>
        <button type="submit" class="btn btn-primary start">
            <i class="glyphicon glyphicon-upload"></i>
            <span>Start upload</span>
        </button>
        <button type="reset" class="btn btn-warning cancel">
            <i class="glyphicon glyphicon-ban-circle"></i>
            <span>Cancel upload</span>
        </button>
      </div>
 
      <div class="col-lg-5">
        <!-- The global file processing state -->
        <span class="fileupload-process">
          <div id="total-progress" class="progress progress-striped active" role="progressbar" 
                aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
            <div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
          </div>
        </span>
      </div>
    </div>
 
    <div class="table table-striped" class="files" id="previews">
      <div id="preview-template" class="file-row">
        <!-- This is used as the file preview template -->
        <div>
            <span class="preview"><img data-dz-thumbnail /></span>
        </div>
        <div>
            <p class="name" data-dz-name></p>
            <strong class="error text-danger" data-dz-errormessage></strong>
        </div>
        <div>
            <p class="size" data-dz-size></p>
            <div class="progress progress-striped active" role="progressbar" 
                    aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
              <div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
            </div>
        </div>
        <div>
          <button class="btn btn-primary start">
              <i class="glyphicon glyphicon-upload"></i> <span>Start</span>
          </button>
          <button data-dz-remove class="btn btn-warning cancel">
              <i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel</span>
          </button>
          <button data-dz-remove class="btn btn-danger delete">
            <i class="glyphicon glyphicon-trash"></i> <span>Delete</span>
          </button>
        </div>
      </div>
    </div>
</div>
 
...
 
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="./lib/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="./lib/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="./lib/ie10-viewport-bug-workaround.js"></script>
 
<!-- Add Dropzone support -->
<link href="css/dropzone.css" type="text/css" rel="stylesheet" /> 
<script src="lib/dropzone.js"></script>
<script src="dropzone-dz3.js"></script>
<script>
  $(function() {
      //var myDropzone = new Dropzone("#form-multiple-file-upload2");
      //myDropzone.on("addedfile", function(file) {
      //  /* Maybe display some more file information on your page */
      //});
  });
</script>  
file dropzone-dz3.js
//-----------------------------------------------------------------
// Programmatically instantiate a Dropzone (dz3)
//-----------------------------------------------------------------
 
// Get the template HTML and remove it from the doument
var previewNode = document.querySelector("#preview-template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
 
//var myDropzone = new Dropzone(document.body, { // Make the whole body a dropzone
//var myDropzone = new Dropzone(document.querySelector("#dropzone3"), { // Make the DIV 'form-single-file-upload' a dropzone (using js)
var myDropzone = new Dropzone("#dropzone3", { // Make the DIV 'dropzone3' a dropzone (using jquery)
  url: "upload.php",     // Set the target url
  paramName: "file",     // The name that will be used to transfer the file
  thumbnailWidth: 80,
  thumbnailHeight: 80,
  parallelUploads: 20,
  previewTemplate: previewTemplate,
  autoQueue: false, // Make sure the files aren't queued until manually added
  previewsContainer: "#previews", // Define the container to display the previews
  clickable: ".fileinput-button" // Define the element that should be used as click trigger to select files.
});
 
myDropzone.on("addedfile", function(file) {
  // Hookup the start button
  file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
});
 
// Update the total progress bar
myDropzone.on("totaluploadprogress", function(progress) {
  document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
 
myDropzone.on("sending", function(file) {
  // Show the total progress bar when upload starts
  document.querySelector("#total-progress").style.opacity = "1";
  // And disable the start button
  file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
 
// Hide the total progress bar when nothing is uploading anymore
myDropzone.on("queuecomplete", function(progress) {
  document.querySelector("#total-progress").style.opacity = "0";
});
 
// Setup the buttons for all transfers
// The "add files" button doesn't need to be setup because the config
// `clickable` has already been specified.
document.querySelector("#actions .start").onclick = function() {
  myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function() {
  myDropzone.removeAllFiles(true);
};
Server Side Upload Handling
file upload.php
<?php
$ds          = DIRECTORY_SEPARATOR;
$storeFolder = 'uploads';   // for development
$success     = false;
$log         = print_r($_POST, true) . "\r\n";  // debug
 
if (!empty($_FILES)) {
    $log .= print_r($_FILES['file'], true) . "\r\n";
 
    $tempFile   = $_FILES['file']['tmp_name'];                    
    $origFile   = $_FILES['file']['name'];
    $targetExt  = pathinfo($origFile, PATHINFO_EXTENSION);
    $targetDir  = dirname( __FILE__ ) . $ds. $storeFolder . $ds;  
    $targetFile = ( !empty($_POST['target-file-name']) ? $_POST['target-file-name'] . '.' . $targetExt : $origFile );
    $targetPath = $targetDir . $targetFile;
    $log .= "Normalized target file: $targetPath.\r\n"; // debug
 
    $targetFile = clean_file_uploaded_name($targetFile);
    if (check_file_uploaded_name($targetFile)) {
        if (check_file_uploaded_length($targetFile)) {
            if (check_file_supported($targetFile)) {
                move_uploaded_file($tempFile, $targetPath);
                $success = true;
                $log .= "Added file $targetPath.\r\n"; // debug
            } else {
                $log .= "Error: File format [$targetExt] not supported.\r\n";   // debug
            }
        } else {
            $log .= "Error: File length not supported.\r\n";   // debug
        }
    } else {
        $log .= "Error: File name contains invalid characters.  " . 
                "Make sure it only uses alphanumeric, -, or _ characters.\r\n";   // debug
    }
}
if (!$success) {
    $log .= "Error: Failed to upload file.\r\n";   // debug
}
file_put_contents('upload.log', $log); // debug
 
 
 
// Security checks before calling move_uploaded_file()
// Reference: http://php.net/manual/en/function.move-uploaded-file.php
 
// First : make sure that the file is not empty.
 
/**
* Make sure the file name in English characters, numbers and (_-.) symbols, for more protection.
* Check $_FILES[][name]
*
* @param (string) $filename - Uploaded file name.
* @author Yousef Ismaeil Cliprz
*/
function check_file_uploaded_name($filename)
{
    return (bool) ((preg_match("`^[-0-9A-Z_\.]+$`i", $filename)) ? true : false);
}
 
function clean_file_uploaded_name($filename)
{
    return str_ireplace(" ", "_", $filename); // replace spaces with underscores
}
 
/**
* Make sure that the file name not bigger than 250 characters.
* Check $_FILES[][name] length.
*
* @param (string) $filename - Uploaded file name.
* @author Yousef Ismaeil Cliprz.
*/
function check_file_uploaded_length($filename)
{
    return (bool) ((mb_strlen($filename, "UTF-8") < 225) ? true : false);
}
 
// Check File extensions and Mime Types that you want to allow in your project. 
// You can use : pathinfo() http://php.net/pathinfo
// or you can use regular expression for check File extensions as in example
// #^(gif|jpg|jpeg|jpe|png)$#i
// or use in_array() checking.
function check_file_supported($filename)
{
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    $ext_type = array('gif', 'jpg', 'jpe', 'jpeg', 'png', 'bmp', 'pdf', 'mpg', 'mp4', 'avi', 'mov', 'txt');
    return (in_array($ext, $ext_type));   // does it have valid extension?
}    
 
// Check file size and make sure the limit of php.ini to upload files is what you want. 
// You can start from http://www.php.net/manual/en/ini.core.php#ini.file-uploads
 
// Check the file content to see whether is has a bad codes or something
// http://php.net/manual/en/function.file-get-contents.php.