質問
さて、現在、SWF が PHP ファイルにアクセスしています。このファイルは、指定したすべてのファイルを検索し、それらのサイズを加算して、結合したサイズを 1 つの数値として返します。次に、この数値を ProgressEvent リスナーで使用して、Web サイトの特定のセクションでダウンロードされているファイルの現在の割合を判断します。
とても簡単ですよね?さて、その PHP ファイルを使用することは問題外であり、必要な数値を取得するために外部スクリプトをヒットさせる代わりに、SWF 内ですべてを実行しようとしています。
ファイルをフラッシュにロードし始める前にファイルのサイズを取得する良い方法はありますか?プリローダーを 0 ~ 100% のプリローダーにする必要があるため、実際に開始する前にダウンロードする合計バイト数が必要です。
私が考えた 1 つの考えは、ファイル URL を保持する配列を調べてロードを開始し、ロードを表示せずに getTotalBytes を実行し、最初のティックでロードを強制終了し、合計バイト数をすべて合計してから、実際のダウンロード プロセスを開始することでした。この方法は非常に醜く見えますし、ユーザーがサイトでプリローダーにアクセスするたびに、すべてのファイルを実行し、合計を見つけて実際にダウンロードを開始するのにおそらく 1 ~ 2 秒かかるため、膨大な時間の無駄になります。
これらのファイルのサイズを取得するためにフラッシュの外部に行かずに、この問題を解決するより良い解決策はありますか?
解決
ファイルのサーバーに対して HTTP HEAD リクエストを実行できます。これにより、ヘッダー情報 (ファイル サイズを含む) が返されますが、実際のファイルは返されません。その後、GET リクエストを発行してファイルをロードできます。
http://www.w3.org/プロトコル/rfc2616/rfc2616-sec9.html
(セクション 9.4 HEAD を確認してください)
私ならおそらく 2 段の進行状況バー (2 つの進行状況バー) を作成するでしょう。1 つは全体的な進行状況 (0 ~ 100%) を示し、もう 1 つはファイルごとの進行状況 (各ファイルのダウンロード時) を示します。
こうすることで、ロードするファイルの数がわかっている限り、最初にサーバーにアクセスしてファイル サイズを取得することなく、全体の進行状況を実行できます。
マイク・チャンバー
メッシュ@adobe.com
他のヒント
Mike Chamber のアイデアは役に立ちますが、いずれにしてもファイルごとにリクエストを作成する必要があるため、サーバーサイドのものを使用するよりも遅くなります。これは基本的に自分で言っているのと同じですが、ヘッダーを明示的に要求している場合はわずかに速くなります。ソケットを使用してリクエストを実行します。
var socket : Socket = new Socket( ); socket.addEventListener( Event.CONNECT, connectHandler ); socket.addEventListener( ProgressEvent.SOCKET_DATA, dataHandler ); socket.connect( "yourserver.com", 80 ); function connectHandler( event : Event ) : void { var headers : String = "HEAD yourfilename.ext http/1.1\r\n"; headers += "Host: yourserver.com\r\n"; headers += "\r\n\r\n"; socket.writeUTFBytes( headers ); socket.flush( ); } function dataHandler( event : ProgressEvent ) : void { trace( "Received headers\n" ); trace( socket.readUTF( socket.bytesAvailable ) ); }
ファイルのロード方法を制御することが絶対に必要な場合は、HTTP HEAD リクエストを作成するという Mike Chambers の提案が正しい方法だと思います。
ただし、そうしない正当な理由がない限り、すべてのファイルを一度にロードし、各ファイルの getBytesTotal メソッドからファイル サイズを取得するだけです。Flash はブラウザからネットワーク スタックを取得するため、実際に同時にロードされるファイルの数は、(ユーザー定義可能な) ブラウザの設定に従います。
以下は単なる例です。実際のケースでは、Timer は使用しません。配列または XML オブジェクトを for ループで反復処理します。それがうまく機能するかどうかは関係なく、基本的にはループの最後に達すると (例:if(i == (length - 1)) 合計が得られたので、実際の事前読み込みを開始する機能を呼び出します。ここで、配列または XML オブジェクトを再度繰り返し処理しますが、今回は for ループではなく、各アセットがロードされたときにのみ実行します。この非同期メソッドはそこに留まり、ロードされたデータの量を比較し、それを以前に見つかった合計で割ってパーセンテージを算出します。
var totalBytes:Number = 0; var loader:Loader = new Loader(); var request:URLRequest = new URLRequest(); request.url = 'badfish.jpg'; var timer:Timer = new Timer(200); timer.addEventListener(TimerEvent.TIMER, onTimer); function onTimer(e:TimerEvent) { loader.load(request); loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress); } function onProgress(e:ProgressEvent):void { totalBytes+=e.bytesTotal; trace(e.bytesTotal,totalBytes); loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress); } timer.start();