Skip to content

Instantly share code, notes, and snippets.

@corpix
Created November 22, 2011 06:15
Show Gist options
  • Save corpix/1385028 to your computer and use it in GitHub Desktop.
Save corpix/1385028 to your computer and use it in GitHub Desktop.
HTML5 FileReader
var fileUploads = function(input){
var self = this;
if(input.length > 0 && !window.FileReader){ // TODO failover
$.sticky('Ваш браузер не поддерживает HTML5 FileReader, обновитесь.');
return false;
}
this.input = input;
var parent = input.parent()
, dropbox = self.dropbox = $('<div class="dropbox">')
, list = this.list = $('<ul class="list">');
this._list = [];
dropbox.append(list);
$(input).change(function(){ self._addFiles(this.files); });
this._dropAreaBindings(dropbox);
dropbox.append($('<div class="clear">'));
parent.append(dropbox);
parent.find('.sendFiles').click(this._upload(parent));
return this;
}
fileUploads.prototype._dropAreaBindings = function(area){
var self = this;
area.bind({
dragenter: function(){
$(this).addClass('hover');
return false;
},
dragover: function(){ return false; },
dragleave: function(){
$(this).removeClass('hover');
return false;
},
drop: function(e){
$(this).removeClass('hover');
e = e || window.event;
e.preventDefault();
e = e.originalEvent || e;
self._addFiles(e.files || e.dataTransfer.files);
return false;
}
});
}
fileUploads.prototype._addFiles = function(files){
var img = $('<img>')
, self = this;
for (var i = 0; i < files.length; i++) {
(function(i){
var reader = new FileReader()
, file = files[i];
reader.onload = function(event){
self._list.push(file);
var _img = img.clone().attr({
src: event.target.result,
title: file.name,
alt: file.name
});
_img.width(100);
var li = $('<li>')
, remove = $('<a class="clickable">');
li.bind('mouseenter mouseleave', function(){
$(this).find('a').toggle();
});
remove.click(function(){
var index = $(this).parent().index();
self._removeFile.apply(self, [ index ])
return false;
});
li.append(remove);
self.list.append(li.append(_img));
}
reader.readAsDataURL(file);
})(i);
}
}
fileUploads.prototype._removeFile = function(index){
this._list.splice(index, 1);
this.list.find('li:eq('+index+')').remove();
}
fileUploads.prototype._upload = function(parent){
var self = this
, url = this.input.attr('data-url')
, name = this.input.attr('name');
if(!url)
url = this.input.closest('form').attr('action');
return function(){
for(var i in self._list){
new self._uploader({
file: self._list[i],
url: url,
fieldName: name,
onprogress: function(percents) { self.input.trigger('progress', percents); },
oncomplete: function(done, data) { self.input.trigger('res', [done, data]); }
});
}
return false;
}
}
fileUploads.prototype._uploader = function(params) {
if(!params.file || !params.url) {
return false;
}
this.xhr = new XMLHttpRequest();
this.reader = new FileReader();
this.progress = 0;
this.uploaded = false;
this.successful = false;
this.lastError = false;
var self = this;
self.reader.onload = function() {
self.xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
self.progress = (e.loaded * 100) / e.total;
if(params.onprogress instanceof Function) {
params.onprogress.call(self, Math.round(self.progress));
}
}
}, false);
self.xhr.upload.addEventListener('load', function(){
self.progress = 100;
self.uploaded = true;
}, false);
self.xhr.upload.addEventListener('error', function(){
self.lastError = {
code: 1,
text: 'Error uploading on server'
};
}, false);
self.xhr.onreadystatechange = function () {
var callbackDefined = params.oncomplete instanceof Function;
if (this.readyState == 4) {
if(this.status == 200) {
if(!self.uploaded) {
if(callbackDefined) {
params.oncomplete.call(self, false);
}
} else {
self.successful = true;
if(callbackDefined) {
params.oncomplete.call(self, true, this.responseText);
}
}
} else {
self.lastError = {
code: this.status,
text: 'HTTP response code is not OK ('+this.status+')'
};
if(callbackDefined) {
params.oncomplete.call(self, false);
}
}
}
};
self.xhr.open('POST', params.url);
var boundary = '----FileReaderBoundary' + Math.round((new Date()).getTime() / 1000);
self.xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary='+boundary);
if (window.csrf)
self.xhr.setRequestHeader('X-CSRF-Token', csrf);
var body = '--' + boundary + '\r\n';
body += 'Content-Disposition: form-data; name="'+(params.fieldName || 'file')+'"; filename="' + params.file.name + '"\r\n';
body += 'Content-Type: ' + params.file.type + '\r\n\r\n';
body += self.reader.result + '\r\n';
body += '--' + boundary + '--';
if(self.xhr.sendAsBinary) {
// firefox
self.xhr.sendAsBinary(body);
} else {
// chrome (W3C spec.)
self.xhr.send(body);
}
}
self.reader.readAsBinaryString(params.file);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment