2017-01-28 32 views
2

私は、ovhサーバー上のSymfonyフレームワークを使用してウェブサイトを作っています。 ユーザーがページを変更すると、すべてのページをリロードしてユーザーエクスペリエンスを向上させるため、新しいXMLHttpRequestを作成します。XMLHttpRequestの進捗状況の追跡とsymfony(CORS)

すべてうまくいきますが、次のページが非同期で読み込まれている間にローディングバーを追加したいと思います。残念ながらlengthComputableパラメータはfalseです。この問題を通過する 、私は論文ラインと応答を送信する前にSymfony3のヘッダを設定しました:

$length = strlen($event->getResponse()->getContent()); 
$event->getResponse()->headers->set('Content-Length', $length); 
$event->getResponse()->headers->set('Accept-Ranges', "bytes"); 
$event->getResponse()->sendHeaders(); 

このトリックは私のローカルの開発サーバーで動作し、lengthComputableがtrueに設定されていると私は計算することができます現在の負荷率。しかし、リモートのdevサーバにすべてを置くと、lengthComputableは再びfalseになります。ここで

は論文に4行使用してレスポンスヘッダーです:これは、元のヘッダーポリシーを横切るように関係している

Accept-Ranges:bytes 
Accept-Ranges:bytes 
Cache-Control:no-cache 
Cache-Control:no-cache 
Content-Encoding:gzip 
Content-Length:3100 
Content-Length:3100 
Content-Type:text/html; charset=UTF-8 
Date:Sat, 28 Jan 2017 12:34:08 GMT 
Server:Apache 
Set-Cookie:PHPSESSID=***; path=/; HttpOnly 
Vary:Accept-Encoding 

(そして、はい、いくつかのパラメータが存在している2回)

Iの事を、私はすることができます解決策が見つかりませんでした。

私は

$responseHeaders->set('Access-Control-Allow-Headers', 'content-type'); 

とさえ

$responseHeaders->set('Access-Control-Allow-Origin', '*'); 

のような他のパラメータを設定しようとした私が続くと論文を試してみました

Symfony2. I can't set Content-Length header

How can I access the Content-Length header from a cross domain Ajax request?

リンク

CORS with php headers

EDIT

私はプロキシを使用していない、と私のサーバーはOVHでホストされています。ここで

が私のJavaScriptコード(例外なし)私のprogress(evt)機能で

ajax_oReq = new XMLHttpRequest(); 
ajax_oReq.addEventListener("progress", progress, false); 
ajax_oReq.addEventListener("load", complete, false); 
ajax_oReq.addEventListener("error", error, false); 
ajax_oReq.addEventListener("abort", error, false); 

params = "ajax=1"; 
if(url.indexOf('?')!=-1){ params = "&"+params; }else{ params = "?"+params; } 

ajax_oReq.open("GET", url+params, true); 
ajax_oReq.send(); 

ですが、私はlengthComputableevtパラメータをログに記録することにより、偽であることがわかります。

私のcomplete(evt)の機能では、私は対応するdivevt.target.responseを入れました。

私はこのコードを使用すると、ページの全長に等しい読み込まれた長さで約500ms後に最後の進捗イベントを受け取ります(したがって、ドキュメントの100%ですが、lengthComputableはfalseです。 totalは0に等しいので、読み込みが終了したら私のヘッダーを見ているので分かります) しかし、complete関数を呼び出すには約5秒もかかります。コンテンツの長さがわからないためです。とにかく、私は私の4行のコード(最初のもの)を削除すると、この問題は消えますが、私はいつもlengthComputable=trueがありません...

ありがとうございました!

+0

あなたのjavascriptを投稿してください。同じブラウザでテストしていますか?あなたのdevサーバーはプロキシの背後にありますか? –

+0

私は自分の投稿を編集したので、クローム、ファイアーフォックス、オペラ、サファリを試してみました。そして、いいえ、私はプロキシを使用していません、私のサーバーはOVH(プロ提供)によってホストされています –

+0

ローカルの場合と同じContent-Encodingを使用していますか? GZIPがここで問題になる可能性があります –

答えて

1

Apacheのmod_deflateがGZIPのレスポンスを圧縮していたため、クライアントサイドでは計算できない長さになっていました(Apacheは私が読んだものから応答をチャンクするので)。

クイック&ダーティな解決策は、Apache設定でそのURLの圧縮を無効にすることです。あなたができない、またはそれが最適化された保つためにしたくない場合は、here

$event->getResponse()->headers->set('x-decompressed-content-length', $length); 

から取られた、より精巧な解決策があり、あなたの進捗状況の機能のようなものになります。

var progress = function (e) { 
     var contentLength; 
     if (e.lengthComputable) { 
     contentLength = e.total; 
     } else { 
     contentLength = e.target.getResponseHeader('x-decompressed-content-length'); 
     } 
     var progress = (e.loaded/contentLength) * 100; 
    }; 

を私は」それはカントーそのうまくいく分からない、それはe.loadedが圧縮または解凍応答に基づいていますが、そのページ

上のあなたのための他の可能なリードがあるされている場合は、また、私は意志、hereから取られ、これを試みることができる依存します私はあなたのコンテンツをどのように設定しているのか分からないので、Symfonyにそれを翻訳させてください。しかし、基本的には、Apacheがそれをしないようにあなた自身があらかじめデータをgzipすることです。

// checks if gzip is supported by client 
    $pack = true; 
    if(empty($_SERVER["HTTP_ACCEPT_ENCODING"]) || strpos($_SERVER["HTTP_ACCEPT_ENCODING"], 'gzip') === false) //replace $_SERVER part with SF method 
    { 
     $pack = false; 
    } 

    // if supported, gzips data 
    if($pack) { 
     $replyBody = gzencode($replyBody, 9, FORCE_GZIP); // Watch out 9 is strong compression 
     // Set SF's Response content with gzipped content here 
     header("Content-Encoding: gzip"); // replace that with appropriate SF method 
    } else { 
     // Set SF's Response content with uncompressed content here 
    } 

    // compressed or not, sets the Content-Length   
    header("Content-Length: " . strlen($replyBody)); // replace that with appropriate SF methods 

だから、かなり多くのあなたのコントローラの最初の2つのifを追加するか、レスポンスの内容を設定しているとして、あなたのイベントリスナーを保存しているところ。

これらは私が見つけることができる最も「ハッキーな」ソリューションの2つです。それ以上に、あなたの推測は私のものと同じくらい良いです、私は前にそれを試していません。

+0

'x-decompressed-content-length'を設定すると、私は驚いていますが、' evt.progress'はそうですロードされたコンテンツの圧縮されていないサイズなので、うまくいきます。どうもありがとうございました ! –

+0

あなたのブラウザがウェブサーバから送信された応答を解凍しているので、驚くべきことではありません。問題ない ;) –

関連する問題