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.