UploadServices.js

150 lines | 4.364 kB Blame History Raw Download

class UploadServices {

    constructor() {

        this.URL_Start = "/UploadFiles/StartUpload";
        this.URL_Upload = "/UploadFiles/UploadBlob";
        this.URL_Cansel = "/UploadFiles/Cansel";

        this.upload_chunk_size = 102400;
        this.ID = -1;

        this._ContinueDownload = false;

        this._file = null;
        this._ParentID = null;

        //Callback события
        //(number progresse)
        this.OnProggresseChange = null;
        //(number id)
        this.OnIDReceived = null;
        //(string Msg)
        this.OnError = null;
    }


    //Считывает часть файла
    //startByte - int позиция начала чтения
    //stopByte - int позиция окончания чтения
    async _ReadBlobAsync(startByte, stopByte) {

        return new Promise(function (resolve, reject) {
            //Считываем часть файла
            let blob = this._file.slice(startByte, stopByte);

            let reader = new FileReader();
            reader.onload = function () {
                resolve(reader.result);
            };
            reader.onerror = reject;

            reader.readAsDataURL(blob);
        }.bind(this));
    }

    //Сообщает серверу о начале загрузки файла, получает ID загрузки
    async _StartUploadAsync() {
        return await $.post(this.URL_Start,
            {
                //ID папки
                'ParentID': this._ParentID,
                //Имя файла
                'Name': this._file.name,
                //Размеры
                'Size': this._file.size
            }
        );
    }

    //Выполняет загрузка блока
    async _UploadBlobAsync(bin_data, ChunkNumb) {

        if (!this._ContinueDownload)
            return { State: true };


        if (bin_data != '') {
            console.log(this.URL_Upload + ChunkNumb);

            var state = await $.post(this.URL_Upload,
                {
                    //ID загрузки
                    'ID': this.ID,
                    //Кусок файла
                    'chunk': bin_data,
                    //Номер куска
                    //'ChunkNumb': ChunkNumb
                }
            )

            return state;
        }
    }


    //Инициирует загрузку файла
    //parent_id - int ID папки для загрузки
    async UploadFileAsync(file, parent_id) {

        this._file = file;
        this._ParentID = parent_id;

        let start_info = await this._StartUploadAsync();
        if (!start_info.State) {
            if (this.OnError != null)
                this.OnError(start_info.Msg);
            return;
        }

        this._ContinueDownload = true;
        this.ID = start_info.ID;
        if (this.OnIDReceived != null)
            this.OnIDReceived(this.ID);

        for (let pos = 0, ChunkNumb = 0; pos < this._file.size; pos += this.upload_chunk_size, ChunkNumb++) {
            if (!this._ContinueDownload)
                return;

            let bin_data = await this._ReadBlobAsync(pos, pos + this.upload_chunk_size);
            let state = await this._UploadBlobAsync(bin_data, ChunkNumb);

            if (!state.State) {
                //alert('Загрузка прервана');

                if (this.OnError != null)
                    this.OnError(state.Msg);
                return;
            }

            // Вычисляем процент отправленного
            let p = Math.round(pos * 100 / file.size);
            console.log('p = ' + p);

            if (this.OnProggresseChange != null)
                this.OnProggresseChange(p);
        }

        this._ContinueDownload = false;
    }

    Cansel() {
        this._ContinueDownload = false;

        //Костыль задержка, чтобы асинхронный загрузчик точно прервал работу
        //и не попытался получить доступ к ужаленному проекту загрузки
        //Возможно зависит от размера блока
        setTimeout(function () { 
            $.post(this.URL_Cansel,
                {
                    //Имя файла
                    'ID': this.ID,
                }
            )
        }.bind(this),
            500);        
    }

}