Created: 16 Jul 11
HTML5 Drag&Drop upload file
The client side
create JS file with the next code:
(function(b){function i(a){a.stopPropagation();a.preventDefault();return!1}function j(a){a.stopPropagation();a.preventDefault();return!1}function k(a){var b=a.dataTransfer.files;a.preventDefault();h(b);return!1}function h(a){b.fn.dropzone.newFilesDropped();for(var c=0;c<a.length;c++){var e=a[c],f=new XMLHttpRequest,d=f.upload;d.fileIndex=c;d.fileObj=e;d.downloadStartTime=(new Date).getTime();d.currentStart=d.downloadStartTime;d.currentProgress=0;d.startData=0;d.addEventListener("progress",l,!1);d.addEventListener("load",
m,!1);f.open(g.method,g.url);f.setRequestHeader("Cache-Control","no-cache");f.setRequestHeader("X-Requested-With","XMLHttpRequest");f.setRequestHeader("X-File-Name",e.fileName);f.setRequestHeader("X-File-Size",e.fileSize);f.setRequestHeader("Content-Type","multipart/form-data");f.send(e);b.fn.dropzone.uploadStarted(c,e)}}function m(){var a=(new Date).getTime()-this.downloadStartTime;b.fn.dropzone.uploadFinished(this.fileIndex,this.fileObj,a)}function l(a){if(a.lengthComputable){var c=Math.round(a.loaded*
100/a.total);if(this.currentProgress!=c){this.currentProgress=c;b.fn.dropzone.fileUploadProgressUpdated(this.fileIndex,this.fileObj,this.currentProgress);var c=(new Date).getTime(),e=c-this.currentStart;if(e>=g.uploadRateRefreshTime)b.fn.dropzone.fileUploadSpeedUpdated(this.fileIndex,this.fileObj,(a.loaded-this.startData)/e),this.startData=a.loaded,this.currentStart=c}}}function n(a){a.preventDefault();h(this.files)}var g={};b.fn.dropzone=function(a){g=b.extend({},b.fn.dropzone.defaults,a);var a=
this.attr("id"),c=document.getElementById(a);b.client.browser=="Safari"&&b.client.os=="Windows"?(a=b("<input>"),a.attr({type:"file"}),a.bind("change",n),a.css({opacity:"0",width:"100%",height:"100%"}),a.attr("multiple","multiple"),a.click(function(){return!1}),this.append(a)):(c.addEventListener("drop",k,!0),a=b("#"+a),a.bind("dragenter",i),a.bind("dragover",j));return this};b.fn.dropzone.defaults={url:"",method:"POST",numConcurrentUploads:3,printLogs:!1,uploadRateRefreshTime:1E3};b.fn.dropzone.newFilesDropped=
function(){};b.fn.dropzone.uploadStarted=function(){};b.fn.dropzone.uploadFinished=function(){};b.fn.dropzone.fileUploadProgressUpdated=function(){};b.fn.dropzone.fileUploadSpeedUpdated=function(){}})(jQuery);(function(){var c={init:function(){this.browser=this.searchString(this.dataBrowser)||"An unknown browser";this.version=this.searchVersion(navigator.userAgent)||this.searchVersion(navigator.appVersion)||"an unknown version";this.OS=this.searchString(this.dataOS)||"an unknown OS"},searchString:function(b){for(var a=0;a<b.length;a++){var c=b[a].string,d=b[a].prop;this.versionSearchString=b[a].versionSearch||b[a].identity;if(c){if(c.indexOf(b[a].subString)!=-1)return b[a].identity}else if(d)return b[a].identity}},
searchVersion:function(b){var a=b.indexOf(this.versionSearchString);if(a!=-1)return parseFloat(b.substring(a+this.versionSearchString.length+1))},dataBrowser:[{string:navigator.userAgent,subString:"Chrome",identity:"Chrome"},{string:navigator.userAgent,subString:"OmniWeb",versionSearch:"OmniWeb/",identity:"OmniWeb"},{string:navigator.vendor,subString:"Apple",identity:"Safari",versionSearch:"Version"},{prop:window.opera,identity:"Opera"},{string:navigator.vendor,subString:"iCab",identity:"iCab"},{string:navigator.vendor,
subString:"KDE",identity:"Konqueror"},{string:navigator.userAgent,subString:"Firefox",identity:"Firefox"},{string:navigator.vendor,subString:"Camino",identity:"Camino"},{string:navigator.userAgent,subString:"Netscape",identity:"Netscape"},{string:navigator.userAgent,subString:"MSIE",identity:"Explorer",versionSearch:"MSIE"},{string:navigator.userAgent,subString:"Gecko",identity:"Mozilla",versionSearch:"rv"},{string:navigator.userAgent,subString:"Mozilla",identity:"Netscape",versionSearch:"Mozilla"}],
dataOS:[{string:navigator.platform,subString:"Win",identity:"Windows"},{string:navigator.platform,subString:"Mac",identity:"Mac"},{string:navigator.userAgent,subString:"iPhone",identity:"iPhone/iPod"},{string:navigator.platform,subString:"Linux",identity:"Linux"}]};c.init();window.$.client={os:c.OS,browser:c.browser}})();
(Just copy-paste it to a JS file)
I've taken here the two files jquery.dnd-file-upload.js and jquery.client.js, minified and combined them into one.
Integration to your page
Use the next code to integrate the DnD to your page.
1. include the jQuery Library
2. include the new created file with the code above
// --------------------
$.fn.dropzone.newFilesDropped = function() {
// new files have been dropped
};
$.fn.dropzone.uploadStarted = function(fileIndex, file) {
// upload of file with given index has started
$('#upload_log').html($('#upload_log').html() + '<br>' + 'started uploading ' + file.name);
};
$.fn.dropzone.uploadFinished = function(fileIndex, file, time) {
// upload of file with given index has finished; upload took *time* mili seconds
$('#upload_log').html($('#upload_log').html() + '<br>' +file.name+ ' finished!');
};
$.fn.dropzone.fileUploadProgressUpdated = function(fileIndex, file, newProgress) {
$('#upload_log').html($('#upload_log').html() + '<br>' + 'progress: ' + newProgress);
};
$.fn.dropzone.fileUploadSpeedUpdated = function(fileIndex, file, KBperSecond) {
// upload speed of given file has changed to *KBPerSecond* KB/s
};
$(document).ready(function(){
$("#dnd_files").dropzone({
url : "ajax_receive_files.php"
});
});
// ----------------------
The server side
I'm using an OOP approach to manage the files on the server side, so here it is:
1.create a class file with the next content
class Html5_Uploader {
private $fileName;
private $contentLength;
private $path;
/**
*
* @param <type> $upload_path - the path with slash
*/
public function __construct($upload_path) {
$this->path = $upload_path;
if (array_key_exists('HTTP_X_FILE_NAME', $_SERVER) && array_key_exists('CONTENT_LENGTH', $_SERVER)) {
$this->fileName = $_SERVER['HTTP_X_FILE_NAME'];
$this->contentLength = $_SERVER['CONTENT_LENGTH'];
} else
throw new Exception("Error retrieving headers");
}
/**
* the callback function receives $new_file_name
*
* @param <type> $callback_function_name
* @param string $prefix
* @return <type>
*/
public function receive($callback_function_name = '', $prefix = null) {
if (is_null($prefix)) {
$prefix = uniqid() . '_';
}
if (!$this->contentLength > 0) {
throw new Exception('No file uploaded!');
}
$new_file_name = $prefix . $this->fileName;
$new_file_path = $this->path . $new_file_name;
file_put_contents(
$this->path . $prefix . $this->fileName,
file_get_contents("php://input")
);
if (!empty($callback_function_name)) {
$callback_function_name($new_file_name);
}
return true;
}
}
( I took this code also from the internet, however I cannot remember the URL, sorry )
Server Side usage
require_once '/html5.uploader.class.php'; // this is the Class file you've just created
function add_to_database($new_file_name) {
// some other operations (if you need...)
}
$uploader = new Html5_Uploader('UploadDirectory/');
$uploader->receive('add_to_database');
Enjoy!
HTML5 is great!
Gregory C.