2

Good day to everybody,

I am new to this forum but will try to do my best to follow the rules. I am currently working on a better solution to have a progress bar when sending an Ajax request that handles a Gzip response.

For this to work, we need lengthComputable, and, unfortunately, when using header("Content-Encoding: gzip") in PHP, the Content-Length cannot be set.

In order to achieve it, I am using this code but I am encountering an issue in ajax as, even if I receive a 200 OK status code, the ajax is considered as failed and I have to do the callback inside the fail.

It s working very well, pako is very fast, but only across the ajax fail.

I am using:

  1. https://github.com/nodeca/pako (pako to handle the ungzip).
  2. Convert integer array to string at javascript (utf8 decodeURIComponent)

Thank you in advance for your help

javascript code:

//-----------------------------------
// ajax progress listener method
//-----------------------------------
!function (e) {
"function" == typeof define && define.amd ? define(["jquery"], e) : "object" 
== typeof exports ? module.exports = e(require("jquery")) : e(jQuery)
}(function (e) {
var n = e.ajax.bind(e);
e.ajax = function (r, t) {
    "object" == typeof r && (t = r, r = void 0), t = t || {};
    var o;
    o = t.xhr ? t.xhr() : e.ajaxSettings.xhr(), t.xhr = function () {
        return o
    };
    var s = t.chunking || e.ajaxSettings.chunking;
    o.upload.onprogress = null;
    var i = n(r, t);
    return i.progress = function (e) {
        var n = 0;
        return o.addEventListener("progress", function (r) {
            var t = [r], o = "";
            3 == this.readyState && s && (o = this.responseText.substr(n), n 
            = this.responseText.length, t.push(o)), e.apply(this, t)
        }, !1), this
    }, i.uploadProgress = function (e) {
        return o.upload && o.upload.addEventListener("progress", function 
    (n) {
            e.apply(this, [n])
        }, !1), this
    }, i
}
});


//-----------------------------------
// atos decodeURIComponent for UTF8
//-----------------------------------
function decodeURI(arr) {
for (var i = 0, l = arr.length, s = '', c; c = arr[i++]; )
    s += String.fromCharCode(
            c > 0xdf && c < 0xf0 && i < l - 1
            ? (c & 0xf) << 12 | (arr[i++] & 0x3f) << 6 | arr[i++] & 0x3f
            : c > 0x7f && i < l
            ? (c & 0x1f) << 6 | arr[i++] & 0x3f
            : c
            );
    return s
}

//-----------------------------------
// ajax request
//-----------------------------------
let progressBar = document.querySelector(".progress");

const request = $.ajax({
    type: "GET",
    url: 'test.php',
    dataType: 'json',
    cache: false,
    data: JSON.stringify({test:true}),
    async: true
}).progress(function (e) {
    if (e.lengthComputable) {
        progressBar.style.width = Math.round((e.loaded * 100) / e.total) + "%";
    }
});

request.done(response => {
    console.log('no success despite 200 OK');
    const result = JSON.parse(decodeURI(pako.ungzip(atob(response))));
    parseJson(result);
}).fail(response => {
    parseJsonerror()
});

function parseJson(result) {
    /* do stuff */
}

function parseJsonerror(){
    /* any error */
}

PHP code:

<?PHP
header('Connection: Keep-Alive');
header("Content-Type: application/json");

/*do stuff*/

$result = json_encode($stuff);
$result64 = base64_encode(gzdeflate($result, 6, ZLIB_ENCODING_DEFLATE));
header("Content-Length:" . mb_strlen($result_list));
echo $result64;

UPDATE

I will answer my own question. Found out the obvious: dataType: "json" in ajax needs to be taken out.

and in PHP: header("Content-type: text/html ; charset=utf-8"); instead of header("Content-Type: application/json");

So this method works wonderfully to have a working progress bar in ajax and keeping a gZip content. Despite the added code in javascript pako and the utf8 decodeURIComponent function are very fast.

to be noted :using this method, content size is 50% smaller than the browser auto gzip method with php header("Content-Encoding: gzip").

Thank you for reading.

tryHarder
  • 31
  • 4

0 Answers0