带有进度条和Gzip响应的Ajax

时间:2017-08-17 20:13:02

标签: javascript php ajax progress-bar gzip

每个人都过得愉快,

我是这个论坛的新手但会尽力遵守规则。 我正在开发一个更好的解决方案,在发送处理Gzip响应的Ajax请求时有一个进度条。

为了实现这一点,我们需要lengthComputable,不幸的是,当在PHP中使用标题(" Content-Encoding:gzip")时,无法设置Content-Length。

为了实现它,我正在使用这段代码,但我在ajax中遇到了一个问题,即使我收到200 OK状态代码,ajax被认为是失败的,我必须在失败中做回调

它工作得非常好,pako非常快,但只有ajax失败。

我正在使用:

  1. https://github.com/nodeca/pako(pako处理ungzip)。
  2. Convert integer array to string at javascript(utf8 decodeURIComponent)
  3. 提前感谢您的帮助

    javascript代码:

    //-----------------------------------
    // 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代码:

    <?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;
    

    更新

    我会回答我自己的问题。 发现明显的: dataType:&#34; json&#34;在ajax中需要被取出。

    并在PHP中: 标题(&#34;内容类型:text / html; charset = utf-8&#34;); 代替 标题(&#34; Content-Type:application / json&#34;);

    因此,这种方法非常有效,可以在ajax中保留一个工作进度条并保留gZip内容。 尽管在javascript pako中添加了代码,但utf8 decodeURIComponent功能非常快。

    需要注意:使用此方法,内容大小比使用php标头的浏览器自动gzip方法小50%(&#34; Content-Encoding:gzip&#34;)。

    感谢您的阅读。

0 个答案:

没有答案