Skip to content

Instantly share code, notes, and snippets.

@v3ss0n
Created September 25, 2015 10:51
Show Gist options
  • Save v3ss0n/19eba95fc4aacd46a157 to your computer and use it in GitHub Desktop.
Save v3ss0n/19eba95fc4aacd46a157 to your computer and use it in GitHub Desktop.
MultiUploader for qooxdoo (Can upload files and blobs and can use it to display nice progressbar) .
// License LGPL
// Requires John's Zenesis UploadMgr addon and based upon it
// http://qooxdoo.org/contrib/project/uploadmgr
// With this , we can use it to upload multiple files in ajax way , without needing UI Widget.
// Useful for uploading Blobs and files .
qx.Class.define("phwabe.utils.MultiUploader", {
extend: com.zenesis.qx.upload.AbstractHandler,
construct: function(uploader) {
this.base(arguments);
console.info("upload_url", uploader)
this.__queue = [];
this.__current = [];
this.__params = {};
this.__uploadUrl = uploader;
},
members: {
/*
* @Override
*/
groupID: null,
addFile: function(input) {
var files = this._createFile(input);
if (!qx.lang.Type.isArray(files)) {
this._addFile(files);
} else
for (var i = 0; i < files.length; i++) {
this._addFile(files[i]);
}
},
_createFile: function(input) {
console.info("input_is", input)
// if (typeof input !== 'Array') {
// input = [input];
// }
var bomFiles = []
for (var key in input) {
bomFiles.push(input[key])
}
if (bomFiles.length === 2) {
this.groupID = this.__genShortID()
} else {
this.groupID = "firefox"
}
if (!bomFiles || !bomFiles.length)
this.debug("No files found to upload via XhrHandler");
var files = [];
for (var i = 0; i < bomFiles.length; i++) {
var bomFile = bomFiles[i];
var id = "upload-" + this._getUniqueFileId()
// fix missing name in Safari 4
//filename = bomFile.fileName != null ? bomFile.fileName : bomFile.name,
var filename = this.groupID + "." + bomFile.type.split("/")[1]
file = new com.zenesis.qx.upload.File(bomFile, filename, id),
//fileSize = bomFile.fileSize != null ? bomFile.fileSize : bomFile.size;
fileSize = typeof bomFile.size !== "undefined" ? bomFile.size : bomFile.fileSize;
file.setSize(fileSize);
files.push(file);
}
return files;
},
/*
* @Override
*/
_doUpload: function(file) {
var xhr = new XMLHttpRequest();
var self = this;
var browserFile = file.getBrowserObject();
console.info("upload_url", this.__uploadUrl)
file.setUserData("com.zenesis.qx.upload.XhrHandler", xhr);
xhr.upload.onprogress = function(e) {
//self.debug("onprogress: lengthComputable=" + e.lengthComputable + ", total=" + e.total + ", loaded=" + e.loaded);
if (e.lengthComputable) {
file.setSize(e.total);
file.setProgress(e.loaded);
}
};
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
var response = xhr.responseText;
//self.debug("xhr server status=" + xhr.status + ", responseText=" + response);
file.setUserData("com.zenesis.qx.upload.XhrHandler", null);
self._onCompleted(file, response);
}
};
if (typeof FormData == "function" || typeof FormData == "object") {
var fd = new FormData();
console.info("Using normal formdata")
// build query string
var action = this.__uploadUrl,
params = this._getMergedParams(file);
for (var name in params)
fd.append(name, encodeURIComponent(params[name]));
fd.append("file", file.getBrowserObject());
xhr.open("POST", action, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", encodeURIComponent(file.getFilename()));
xhr.setRequestHeader("X-Group-ID", this.groupID);
xhr.setRequestHeader("X-MIME", browserFile.type);
xhr.send(fd);
} else {
console.info("Using Multipart/form-data")
var boundary = "--------FormData" + Math.random(),
body = "",
action = this.__uploadUrl,
params = this._getMergedParams(file);
for (var name in params) {
body += "--" + boundary + "\r\n";
body += "Content-Disposition: form-data; name=\"" + name + "\";\r\n\r\n";
body += params[name] + "\r\n";
}
body += "--" + boundary + "\r\n";
body += "Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getFilename() + "\"\r\n";
body += "Content-Type: " + (browserFile.type || "application/octet-stream") + "\r\n\r\n";
function sendAsMime(binaryData) {
body += binaryData + "\r\n";
body += "--" + boundary + "--";
xhr.open("POST", action, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", encodeURIComponent(file.getFilename()));
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
xhr.setRequestHeader("X-Group-ID", this.groupID);
xhr.send(body);
}
if (typeof browserFile.getAsBinary == "function") {
sendAsMime(browserFile.getAsBinary());
} else {
var reader = new FileReader();
reader.onload = function(evt) {
sendAsMime(evt.target.result);
};
reader.readAsBinaryString(browserFile);
}
}
},
_addFile: function(file) {
this.__queue.push(file);
this.fireDataEvent("addFile", file);
},
_cancel: function(file) {
var inCurrent = false;
for (var current = this.__current, i = 0; i < current.length; i++)
if (current[i] == file) {
current.splice(i, 1);
inCurrent = true;
break;
}
for (var queue = this.__queue, i = 0; i < queue.length; i++)
if (queue[i] == file) {
queue.splice(i, 1);
break;
}
file.setState("cancelled");
if (inCurrent)
this._doCancel(file);
this.fireDataEvent("cancelUpload", file);
},
_onCompleted: function(file, response) {
//this.debug("completed: id=" + file.getId() + ", fileName=" + file.getFilename() + ", response=" + response);
var current = this.__current;
for (var i = 0; i < current.length; i++)
if (current[i] == file) {
current.splice(i, 1);
break;
}
file.setResponse(response);
// File state should be uploading or cancelled
if (file.getState() == "uploading") {
file.setState("uploaded");
this.fireDataEvent("completeUpload", file);
}
// Start the next one
this.beginUploads();
},
/**
* Begins spooling uploads to the server, up to the maxConnections
*/
beginUploads: function() {
while (this.__queue.length > 0 && this.__current.length < this.getMaxConnections()) {
var file = this.__queue.shift();
this.__current.push(file);
this.fireDataEvent("beginUpload", file);
file.setState("uploading");
this._doUpload(file);
}
},
/**
* Helper method that produces a final list of parameter values, by merging those
* set in this with those in the file.
* @param file {File} the file object
* @returns {Map} map of parameters to sent to the server
*/
_getMergedParams: function(file) {
var result = {};
for (var name in this.__params) {
var value = this.__params[name];
if (value !== null)
result[name] = value;
}
function merge(obj) {
var names = obj.getParamNames();
for (var i = 0; i < names.length; i++) {
var name = names[i],
value = obj.getParam(name);
if (value !== null)
result[name] = value;
else
delete result[name];
}
}
merge(file);
return result;
},
/*
* @Override
*/
_doCancel: function(file) {
var xhr = file.getUserData("com.zenesis.qx.upload.XhrHandler");
if (xhr) {
xhr.abort();
file.setUserData("com.zenesis.qx.upload.XhrHandler", null);
}
},
__genShortID: function() {
return ("000000" + (Math.random() * Math.pow(36, 6) << 0).toString(36)).slice(-6)
}
},
statics: {
/**
* Detects whether this handler is support on the current browser
* @returns {Boolean}
*/
isSupported: function(requireMultipartFormData) {
var input = document.createElement('input');
input.type = 'file';
var isSupported =
'multiple' in input &&
typeof File != "undefined" &&
typeof(new XMLHttpRequest()).upload != "undefined";
return isSupported;
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment