84 lines
No EOL
2.6 KiB
JavaScript
84 lines
No EOL
2.6 KiB
JavaScript
function Uploader(file, onSuccess, onError, onProgress) {
|
||
|
||
// идентификатор загрузки, чтобы стыковать два потока
|
||
var fileId = file.name + '-' + file.size + '-' + +file.lastModifiedDate;
|
||
fileId = hashCode(fileId);
|
||
|
||
var xhrUpload;
|
||
var xhrStatus;
|
||
|
||
// *!* Закачка: поток НА сервер */!*
|
||
function runUpload(startByte) {
|
||
console.log("run upload from ", startByte);
|
||
xhrUpload = new XMLHttpRequest();
|
||
xhrUpload.onload = xhrUpload.onerror = function() {
|
||
xhrStatus.abort(); // остановить отслеживание прогресса по завершении загрузки
|
||
if (this.status != 200) {
|
||
onError("Upload error " + this.statusText);
|
||
} else {
|
||
onSuccess();
|
||
}
|
||
|
||
};
|
||
xhrUpload.open("POST", "upload", true);
|
||
xhrUpload.setRequestHeader('X-File-Id', fileId);
|
||
xhrUpload.send(file.slice(startByte));
|
||
}
|
||
|
||
// *!* Получать статус: поток С сервера */!*
|
||
function upload() {
|
||
xhrStatus = new XMLHttpRequest();
|
||
xhrStatus.onreadystatechange = function(e) {
|
||
console.log(this);
|
||
}
|
||
|
||
xhrStatus.onprogress = function() {
|
||
var lastByte = getLastProgress(xhrStatus.responseText);
|
||
console.log("lastByte", lastByte);
|
||
if (!xhrUpload) {
|
||
runUpload(lastByte + 1);
|
||
}
|
||
onProgress(lastByte, file.size);
|
||
}
|
||
|
||
xhrStatus.onerror = function() {
|
||
onError("Upload status error " + this.statusText);
|
||
xhrUpload.abort();
|
||
}
|
||
|
||
xhrStatus.open("POST", "status-stream", true);
|
||
xhrStatus.setRequestHeader('X-File-Id', fileId);
|
||
xhrStatus.send();
|
||
}
|
||
|
||
// *!* Функция для чтения количества байт из статуса сервера 12-345-... */!*
|
||
function getLastProgress(response) {
|
||
// читаем число между последним и предпоследним знаком -
|
||
var lastDelimiter = response.lastIndexOf('-');
|
||
if (lastDelimiter < 0) return 0;
|
||
|
||
var prevDelimiter = response.lastIndexOf('-', lastDelimiter - 1);
|
||
return response.slice(prevDelimiter + 1, lastDelimiter);
|
||
}
|
||
|
||
// внешний интерфейс
|
||
this.upload = upload;
|
||
|
||
}
|
||
|
||
|
||
|
||
// вспомогательная функция: получение 32-битного числа из строки
|
||
|
||
function hashCode(str) {
|
||
if (str.length == 0) return 0;
|
||
|
||
var hash = 0,
|
||
i, chr, len;
|
||
for (i = 0; i < str.length; i++) {
|
||
chr = str.charCodeAt(i);
|
||
hash = ((hash << 5) - hash) + chr;
|
||
hash |= 0; // Convert to 32bit integer
|
||
}
|
||
return hash;
|
||
}; |