Skip to content

Instantly share code, notes, and snippets.

@hex-ci
Last active May 6, 2016 18:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hex-ci/e6fcb0c1e6d70f4a47065f04a81ed864 to your computer and use it in GitHub Desktop.
Save hex-ci/e6fcb0c1e6d70f4a47065f04a81ed864 to your computer and use it in GitHub Desktop.
// 文件上传组件
// 浏览器必须支持 XMLHttpRequest 2
var fileUploader = function(fileElement, userOptions) {
var fileEl = $(fileElement);
var xhrObject = null;
var exports = {};
var hasXhr2 = window.XMLHttpRequest && ('upload' in new XMLHttpRequest());
var defaultOptions = {
url: '',
maxSize: 1024 * 1024, // 最大文件大小,默认 1M
fileType: ['png', 'jpg', 'jpeg', 'gif'],
fileTypeBlacklist: [],
maxNumber: 1,
minNumber: 1,
auto: true, // 是否自动上传
onstart: new Function(),
onsucceed: new Function(),
oncomplete: new Function(),
onprogress: new Function(),
oncancel: new Function(),
onerror: new Function(),
onend: new Function()
};
var options = $.extend({}, defaultOptions, userOptions);
exports.on = function(eventName, callback) {
$.event.add(this, eventName, callback);
return this;
};
exports.on('start', options.onstart);
exports.on('succeed', options.onsucceed);
exports.on('complete', options.oncomplete);
exports.on('progress', options.onprogress);
exports.on('cancel', options.oncancel);
exports.on('error', options.onerror);
exports.on('end', options.onend);
exports.options = options;
if (!hasXhr2) {
fileEl.attr('disabled', 'disabled');
}
var uploadFile = function(el) {
if (!hasXhr2) {
return false;
}
var fd = new FormData();
var files = el.files;
$.event.trigger('start', {
fileElement: el,
files: files
}, exports);
// 检查上传文件数量是否合法
if (files.length > options.maxNumber || files.length < options.minNumber) {
$.event.trigger('error', {
error: 'number',
fileElement: el,
files: files
}, exports);
$.event.trigger('end', {
error: 'number',
fileElement: el,
files: files
}, exports);
return false;
}
// 检查文件类型是否合法
var ext = '';
var errorFiles = [];
for (var i = 0; i < files.length; i++) {
ext = files[i].name.substr((~-files[i].name.lastIndexOf(".") >>> 0) + 2);
if (options.fileTypeBlacklist.length > 0 && options.fileTypeBlacklist.contains(ext)) {
errorFiles.push(files[i]);
}
if (options.fileType.length > 0 && !options.fileType.contains(ext)) {
errorFiles.push(files[i]);
}
}
if (errorFiles.length > 0) {
$.event.trigger('error', {
error: 'type',
fileElement: el,
files: errorFiles
}, exports);
$.event.trigger('end', {
error: 'type',
fileElement: el,
files: files
}, exports);
return false;
}
// 检查文件长度是否合法
errorFiles = [];
for (var i = 0; i < files.length; i++) {
if (files[i].size > options.maxSize) {
errorFiles.push(files[i]);
}
}
if (errorFiles.length > 0) {
$.event.trigger('error', {
error: 'size',
fileElement: el,
files: errorFiles
}, exports);
$.event.trigger('end', {
error: 'size',
fileElement: el,
files: files
}, exports);
return false;
}
var name = fileEl.attr('name') || 'file';
if (files.length > 1) {
name += '[]';
}
for (var i = 0; i < files.length; i++) {
fd.append(name, files[i]);
}
var xhr = new XMLHttpRequest(),
upload = xhr.upload;
upload.addEventListener("progress", function (ev) {
if (ev.lengthComputable) {
$.event.trigger('progress', {
fileElement: el,
files: files,
loaded: ev.loaded,
total: ev.total,
percent: (ev.loaded / ev.total) * 100
}, exports);
}
}, false);
upload.addEventListener("load", function (ev) {
$.event.trigger('succeed', {
fileElement: el,
files: files
}, exports);
}, false);
upload.addEventListener("error", function (ev) {
$.event.trigger('error', {
error: 'upload',
fileElement: el,
files: files
}, exports);
}, false);
xhr.addEventListener("error", function (ev) {
$.event.trigger('error', {
error: 'download',
fileElement: el,
files: files
}, exports);
}, false);
xhr.addEventListener("load", function(ev) {
var text = ev.currentTarget.responseText;
var result = null;
result = parseJson(text);
if (!result) {
result = {'errno': 999, 'errmsg': 'Error!', data: []}; // 内部错误
}
var errno = result.errno;
$.event.trigger('complete', {
isSuccess: (errno == 0),
responseData: result,
fileElement: el,
files: files
}, exports);
$.event.trigger('end', {
error: '',
fileElement: el,
files: files
}, exports);
}, false);
xhr.open("POST", options.url);
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.send(fd);
return xhr;
};
var handler = function(e) {
xhrObject = uploadFile(this);
};
var resetFile = function() {
// 加 form
fileEl.wrap('<form style="display:inline;padding:0;margin:0"></form>');
fileEl.parent()[0].reset();
//移除 form
fileEl.unwrap();
};
// 以 onchange 方式上传文件
if (options.auto) {
fileEl.on('change', handler);
fileEl.on('click', function(){
if (Browser.ie) {
resetFile();
}
else {
setTimeout(function(){
resetFile();
}, 1);
}
});
}
// 导出方法
$.extend(exports, {
upload: function() {
if (fileEl.length > 0) {
uploadFile(fileEl[0]);
}
}
});
return exports;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment