Skip to content

Instantly share code, notes, and snippets.

@yuru4c
Last active March 27, 2020 15:49
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 yuru4c/f1e4065a04d8951f5b0469c1430da356 to your computer and use it in GitHub Desktop.
Save yuru4c/f1e4065a04d8951f5b0469c1430da356 to your computer and use it in GitHub Desktop.
複数ファイルアップロード
var Uploader = (function () {
function Uploader(url, name) {
this.chunk = 0;
this.retry = 0;
this.timeout = 0;
this._url = url;
this._name = name;
this._i = -1;
this._j = -1;
this._end();
var self = this;
this._onabort = function (event) {
self.__onabort(event);
};
this._onerror = function (event) {
self.__onerror(event);
};
this._onload = function (event) {
self.__onload(event);
};
this._onprogress = function (event) {
self.__onprogress(event);
};
}
var prototype = Uploader.prototype;
prototype.onprogress = null;
prototype.onabort = null;
prototype.onerror = null;
prototype.onload = null;
prototype.send = function (files) {
if (!this.loading) {
this._start(files);
}
};
prototype.abort = function () {
if (this.loading) {
this._xhr.abort();
}
};
prototype._end = function () {
this.loading = false;
this._list = null;
this._xhr = null;
};
prototype._start = function (files) {
var split = this.chunk >= 0;
var total = 0;
var list = [];
for (var i = 0, l = files.length; i < l; ) {
var file = files[i];
var size = file.size;
var formData = new FormData();
formData.append(this._name, file);
for (i++; i < l; i++) {
file = files[i];
var next = size + file.size;
if (split && next >= this.chunk) break;
size = next;
formData.append(this._name, file);
}
total += size;
list.push(new Chunk(formData, i, total));
}
this.loading = true;
this._list = list;
this._i = 0;
this._next();
};
prototype._next = function () {
if (this._i < this._list.length) {
this._j = 0;
this._send();
} else {
this._done();
}
};
prototype._send = function () {
var xhr = new XMLHttpRequest();
xhr.open("POST", this._url);
xhr.timeout = this.timeout;
xhr.onabort = this._onabort;
xhr.onerror = this._onerror;
xhr.onload = this._onload;
xhr.ontimeout = this._onerror;
xhr.onloadstart = this._onprogress;
if (xhr.upload != null) {
xhr.upload.onprogress = this._onprogress;
}
this._xhr = xhr;
xhr.send(this._list[this._i].formData);
};
prototype._done = function () {
this._end();
if (this.onload != null) {
this.onload();
}
};
prototype._fail = function (event) {
this._end();
if (this.onerror != null) {
this.onerror(event);
}
};
prototype.__onabort = function (event) {
this._end();
if (this.onabort != null) {
this.onabort(event);
}
};
prototype.__onerror = function (event) {
if (this.retry < 0 || this._j < this.retry) {
this._j++;
this._send();
} else {
this._fail(event);
}
};
prototype.__onload = function (event) {
var status = this._xhr.status;
if (status < 400) {
this._i++;
this._next();
} else if (status < 500) {
this._fail(event);
} else {
this.__onerror(event);
}
};
prototype.__onprogress = function (event) {
if (this.onprogress == null) return;
this.onprogress(new Progress(
event.total ? event.loaded / event.total : 0,
this._list[this._i].total,
this._list[this._list.length - 1],
this._i ? this._list[this._i - 1] : null
));
};
function Chunk(formData, index, total) {
this.formData = formData;
this.index = index;
this.total = total;
}
function Progress(progress, total, last, prev) {
var i = prev && prev.index;
var t = prev && prev.total;
this.loadedCount = +i;
this.totalCount = last.index;
this.loaded = t + (total - t) * progress;
this.total = last.total;
}
Progress.prototype.valueOf = function () {
return this.total ?
this.loaded / this.total :
this.loadedCount / this.totalCount;
};
return Uploader;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment