HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/pietvanmierlo/stempelbv.nl/resources/js/kms/attributes/HTML5Uploader.js
/**
 * HTML 5 file uploads that report progress while uploading
 */
class HTML5Uploader {
    constructor(uploadUrl, maxPostSize, maxUploadSize, translations)
    {
        this._constructedSuccessfully = false;

        if(!uploadUrl && !(typeof uploadUrl === 'string')) {
            console.error('Did not get a valid upload url. Not initializing Html5Uploader');
            return;
        }
        this._uploadUrl = uploadUrl;

        if(!maxPostSize) {
            console.error('Did not get the maximum post size. Not initializing Html5Uploader');
            return;
        }
        this._maxPostSize = maxPostSize;

        if(!maxUploadSize) {
            console.error('Did not get the maximum upload size. Not initializing Html5Uploader');
            return;
        }
        this._maxUploadSize = maxUploadSize;

        if(!translations) {
            console.error('Did not get the translations. Not initializing Html5Uploader');
            return;
        }
        this._translations = JSON.parse(translations);

        this._eventMap = {};

        if(!this.isSupported()) {
            console.warn('HTML 5 file upload is not supported. Not initializing Html5Uploader');
            return;
        }

        this.csrfTokenContainer = document.querySelector('meta[name="csrf-token"]');
        if(!this.csrfTokenContainer) {
            console.error('No csrf-token could be found in a meta tag with name "csrf-token". Not initializing Html5Uploader');
            return;
        }

        this._constructedSuccessfully = true;
    }

    /**
     * Returns true if the browser supports HTML 5 uploading. false if not
     * @return {boolean}
     */
    isSupported()
    {
        return window.FormData !== undefined;
    }

    /**
     * @param {File} file
     */
    receiveFile(file)
    {
        if(!this.isSupported()) {
            console.error('HTML 5 file upload is not supported. Not uploading file.');
            return;
        }
    }

    /**
     * @param {File} file
     * @param {string} extraData
     */
    upload(file, extraData)
    {
        if(!this._verifyFileSizeOrShowError(file)) return;

        if(this._constructedSuccessfully === false) return;

        let self = this;

        let formData = new FormData();
        formData.append(file.name, file);
        formData.append('extraData', extraData);

        let request = new XMLHttpRequest();
        let uploadRequest = request.upload;

        uploadRequest.addEventListener("progress", (function(file, extraData) {
            return function(event) {
                self._updateProgress(file, event, extraData);
            };
        })(file, extraData));

        request.addEventListener("loadstart", (function(file, extraData) {
            return function(event) {
                self._uploadStart(file, extraData);
            };
        })(file, extraData));

        request.addEventListener("error", (function(file, extraData) {
            return function(event) {
                self._uploadFailed(file, 'general error', extraData);
            };
        })(file, extraData));

        request.addEventListener("abort", (function(file, extraData) {
            return function(event) {
                self._uploadCanceled(file, extraData);
            };
        })(file, extraData));

        request.onreadystatechange = (function(file, extraData) {
            return function() {
                if(request.readyState === 4) {
                    if(request.status === 200) {
                        self._uploadComplete(file, request.responseText, extraData);
                    } else {
                        self._uploadFailed(file, request.responseText, extraData)
                    }
                }
            }
        })(file, extraData);

        request.open('POST', this._uploadUrl);

        request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        request.setRequestHeader('X-CSRF-TOKEN', this.csrfTokenContainer.getAttribute('content'));

        request.send(formData);
    }

    /**
     * Returns true if the file size is lower then the maximum allowed server upload size.
     * Or shows an alert and returns false if it is bigger then the allowed server upload size.
     *
     * @param {File} file
     * @return {boolean}
     * @private
     */
    _verifyFileSizeOrShowError(file) {
        if(file.size > this._maxPostSize || file.size > this._maxUploadSize) {
            //Calculate file size and max file size to megabytes
            let fileSizeInMegaBytes = file.size / (1024 * 1024);
            let maxSizeInMegaBytes = ((this._maxUploadSize > this._maxPostSize) ? this._maxPostSize : this._maxUploadSize) / (1024 * 1024);

            //Round this sizes to 2 decimals
            fileSizeInMegaBytes = Math.round(fileSizeInMegaBytes * 100) / 100;
            maxSizeInMegaBytes = Math.round(maxSizeInMegaBytes * 100) / 100;

            //Gather translation texts
            let introText = this._translations.file_to_big;
            let maxFileSizeUploadTranslation = this._translations.max_file_size_upload;
            let fileSizeUploadTranslation = this._translations.file_size_upload;

            //Assemble alert message
            let alertText = introText+'\n\n'
                +maxFileSizeUploadTranslation+maxSizeInMegaBytes+' MB\n'
                +fileSizeUploadTranslation+fileSizeInMegaBytes+' MB\n';

            //Show alert message and return false
            alert(alertText);
            return false;
        }

        //File size is fine. Return true
        return true;
    }

    /**
     * @param {File} file
     * @param {ProgressEvent} event
     * @param extraData
     * @private
     */
    _updateProgress (file, event, extraData) {
        if (event.lengthComputable) {
            let percentComplete = Math.ceil(event.loaded / event.total * 100);
            this._triggerEvent('updateProgress', [file, percentComplete, extraData]);
        } else {
            // Unable to compute progress information since the total size is unknown
            this._triggerEvent('updateProgress', [file, null, extraData]);
        }
    }

    /**
     * @param {File} file
     * @param extraData
     * @private
     */
    _uploadStart(file, extraData)
    {
        this._triggerEvent('uploadStart', [ file, extraData ]);
    }

    /**
     * @param {File} file
     * @param {string} responseText
     * @param extraData
     * @private
     */
    _uploadComplete(file, responseText, extraData) {
        this._triggerEvent('uploadComplete', [ file, responseText, extraData ]);
    }

    /**
     * @param {File} file
     * @param extraData
     * @private
     */
    _uploadFailed(file, extraData) {
        this._triggerEvent('uploadFailed', [ file, extraData ]);
    }

    /**
     * @param {File} file
     * @param extraData
     * @private
     */
    _uploadCanceled(file, extraData) {
        this._triggerEvent('uploadCanceled', [ file, extraData ]);
    }

    /**
     * @param {int} fileId
     * @private
     */
    _deleteStart(fileId) {

    }

    /**
     * @param {int} fileId
     * @private
     */
    _deleteComplete(fileId) {
        // console.log('HTML5Uploader: deleted file with id: '+fileId);
        this._triggerEvent('deleteComplete', fileId );
    }

    /**
     * @param {int} fileId
     */
    _deleteFail(fileId) {
        // console.error('HTML5Uploader: could not delete file with id: '+fileId);
        this._triggerEvent('deleteFail', fileId );
    }

    /**
     * Registers a event to a callback and returns the a reference to the event handler for that specific event
     *
     * @param event (string)
     * @param callback (callable)
     */
    on(event, callback)
    {
        if(this._constructedSuccessfully === false) return;

        if(!this._eventMap.hasOwnProperty(event)) this._eventMap[event] = [];
        return this._eventMap[event].push(callback);
    }

    /**
     * Call event callbacks
     *
     * @param event (string)
     * @param eventArgs (array) an array of arguments to pass to the callback
     * @private
     */
    _triggerEvent(event, eventArgs) {
        if(!this._eventMap.hasOwnProperty(event)) return;

        let nEvents = this._eventMap[event].length;
        for(let index = 0; index < nEvents; index++)
        {
            let callback = this._eventMap[event][index];
            if(eventArgs && eventArgs.length > 0) {
                callback.apply(this, eventArgs)
            } else {
                callback.call(this);
            }
        }
    }
}