Flash/Flex アップローダでアップロード進行状況を取得する (Flashアップローダのアップロード進捗取得) - Action Script

Flashのアップローダーでアップロード状況を取得する方法を紹介します。
こちらの記事で紹介したファイルアップローダーにアップロードの進捗状況を表示するようにします。

しくみ

private var file:FileReference = new FileReference();
...
file.addEventListener(ProgressEvent.PROGRESS, UploadProgress);
file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, UploadResult);
FileReferenceオブジェクトのaddEventLisner()メソッドで、 ProgressEvent.PROGRESSを与えてメソッドを登録するとアップロードの進捗イベントリスナとしてメソッドを登録できます。また、DataEvent.UPLOAD_COMPLETE_DATAを与えてメソッドを登録するとデータのアップロード完了イベントリスナを登録できます。

プログラム

UI

下図のUIを準備します。ラベルを2つ、ボタンを1つ、プログレスバーを1つ配置します。


各コントロールのIDは次の通りです。
コントロール種類ID
ラベルlabel_dir
ラベルlabel_message
ボタン(未設定)
プログレスバーprogressBar_upload

コード

下記コードを記述します。
index.template.html ファイル内の
var flashvars = {};
var flashvars = {dir:"(アップロードするWebディレクトリ)", 
  handler:"(アップロード先URL)", pageurl:"遷移先URL(または、現在のページURL)"};
に変更します。
FileUpload.mxml (クライアント部)
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               creationComplete="initApp()"
               width="360" height="100" minWidth="150" minHeight="60">
  
  <fx:Script>
    <![CDATA[
      import mx.utils.URLUtil;
      private var Dir:String;
      private var UploadHandler:String;
      private var CurrentPage:String;
      private var file:FileReference = new FileReference();
      
      protected function initApp():void
      {
        progressBar_upload.mode = "manual";
        
        UploadHandler = this.parameters["handler"];
        Dir = this.parameters["dir"];
        CurrentPage = this.parameters["pageurl"];
        
        label_dir.text = Dir;
        label_message.text="アップロードボタンを押してファイルを選択してください。";
     }
      
      protected function button1_clickHandler(event:MouseEvent):void
      {
        file.addEventListener(Event.SELECT, FileSelected);
        file.browse();
      }
      
      private function FileSelected(event:Event):void{
        var FileName:String = file.name;
        var req:URLRequest = new URLRequest(UploadHandler+"?dir="+Dir);
        req.method = URLRequestMethod.POST;
       
        file.addEventListener(ProgressEvent.PROGRESS, UploadProgress);
        file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, UploadResult);
        file.addEventListener(Event.COMPLETE, UploadComplete);       
        file.upload(req,"File");
      }
      
      private function UploadProgress(event:ProgressEvent):void {
        label_message.text = event.bytesLoaded + "/" + event.bytesTotal + " byte";
        progressBar_upload.minimum = 0;
        progressBar_upload.maximum = 100;

        var per:Number = (event.bytesLoaded / event.bytesTotal) * 100;
        progressBar_upload.setProgress(per,100);
        progressBar_upload.label="upload " + Math.floor(per) + "%";
        
        trace("bytesTotal=" + event.bytesTotal);
        trace("bytesLoaded=" + event.bytesLoaded);
      }
      
      private function UploadResult(event:DataEvent):void
      {
        trace("result:" + event.data);
      }

      private function UploadComplete(event:Event):void{
        label_message.text="アップロードが完了しました。";
        trace("complete");

        if (CurrentPage != ""){
          var request:URLRequest;
          request = new URLRequest(CurrentPage);
          navigateToURL(request);
        }
      }
    ]]>
  </fx:Script>
  
  <fx:Declarations>
    <!-- 非ビジュアルエレメント (サービス、値オブジェクトなど) をここに配置 -->
  </fx:Declarations>
  <s:Button x="9" y="50" label="アップロード" click="button1_clickHandler(event)"/>
  <s:Label id="label_dir" x="10" y="10" text="label_dir"/>
  <s:Label id="label_message" x="10" y="30" text="label_message"/>
  <mx:ProgressBar id="progressBar_upload" x="105" y="50" width="245" label="Upload"/>
</s:Application>

解説

アプリケーション初期化時に、プログレスバーのmodeプロパティに"manual"を設定し、マニュアルモードに変更します。また、FlashVarsからパラメータを取得します。今回のバージョンではファイルのポスト先のジェネリックくハンドラーのURL、ファイルアップロード先のディレクトリ名、アップロード後の遷移ページのURLをFlashVarsから取得します。
protected function initApp():void
{
  progressBar_upload.mode = "manual";
      
  UploadHandler = this.parameters["handler"];
  Dir = this.parameters["dir"];
  CurrentPage = this.parameters["pageurl"];
        
  label_dir.text = Dir;
  label_message.text="アップロードボタンを押してファイルを選択してください。";
}

アップロードボタンクリックハンドラです。
protected function button1_clickHandler(event:MouseEvent):void
{
  file.addEventListener(Event.SELECT, FileSelected);
  file.browse();
}

ファイル選択決定時のリスナー(イベントハンドラ)です。アップロードするファイル名はFileReference.nameプロパティから取得します。またアクセスメソッドはPOSTに設定します。
addEventListenerメソッドを呼び出し、ファイルのアップロードの経過リスナー、データのアップロード完了リスナー、アップロード完了リスナーを登録します。リスナー登録後 uppload()メソッドによりファイルアップロードを開始します。
private function FileSelected(event:Event):void{
  var FileName:String = file.name;
  var req:URLRequest = new URLRequest(UploadHandler+"?dir="+Dir);
  req.method = URLRequestMethod.POST;
       
  file.addEventListener(ProgressEvent.PROGRESS, UploadProgress);
  file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, UploadResult);
  file.addEventListener(Event.COMPLETE, UploadComplete);       
  file.upload(req,"File");
}

アップロード進捗リスナで、アップロードの状況と、プログレスバーの表示を更新します。 event.bytesLoadedで読み込み済みのファイルサイズ、event.bytesTotalでファイルのサイズを取得できます。これらの情報を用いてアップロードの進捗状況を計算しています。
private function UploadProgress(event:ProgressEvent):void {
  label_message.text = event.bytesLoaded + "/" + event.bytesTotal + " byte";
  progressBar_upload.minimum = 0;
  progressBar_upload.maximum = 100;

  var per:Number = (event.bytesLoaded / event.bytesTotal) * 100;
  progressBar_upload.setProgress(per,100);
  progressBar_upload.label="upload " + Math.floor(per) + "%";
        
  trace("bytesTotal=" + event.bytesTotal);
  trace("bytesLoaded=" + event.bytesLoaded);
}

データのアップロード完了リスナーです。traceでデバッグ用のメッセージを表示しています。
private function UploadResult(event:DataEvent):void
{
  trace("result:" + event.data);
}

アップロード完了リスナーでは、メッセージラベルにアップロードが完了した旨のメッセージを表示し、その後、FlashVarsで指定された遷移先URLへ遷移します。遷移先URLに何も指定されていない場合はページ遷移しない動作とします。
private function UploadComplete(event:Event):void{
  label_message.text="アップロードが完了しました。";
  trace("complete");

  if (CurrentPage != ""){
    var request:URLRequest;
    request = new URLRequest(CurrentPage);
    navigateToURL(request);
  }
}

FileUpload.ashx.cs (サーバー部)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Collections.Specialized;

namespace WebFileManager
{
  /// <summary>
  /// FileUpload の概要の説明
  /// </summary>
  public class FileUpload : IHttpHandler
  {

    public void ProcessRequest(HttpContext context)
    {
      if (context.Request.HttpMethod == "GET") {
        context.Response.ContentType = "text/plain";
        context.Response.Write("This handler only support POST method.");
      }
      else if (context.Request.HttpMethod == "POST") {
        string CurrentDir = context.Request.QueryString["dir"];

        if (CurrentDir == null) {
          CurrentDir = "";
        }

        HttpPostedFile content = context.Request.Files["File"];

        string ServerRoot = System.Configuration.ConfigurationManager.AppSettings["rootURI"];
        string ServerPath = ServerRoot  + CurrentDir + "/" + content.FileName;
        string FilePath = context.Server.MapPath(ServerPath);

        content.SaveAs(FilePath);
        context.Response.Write("+OK Upload File is success.");
      }
    }

    public bool IsReusable
    {
      get
      {
        return false;
      }
    }
  }
}

解説

詳細はこちらの記事を参照してください。ここで紹介しているサーバーとほぼ同じものを用いています。

実行結果

サーバー側のプログラムを配置し、クライアント側のFlexアプリを起動します。下図の画面が表示されます。[アップロード]ボタンを押します。


ファイル選択ダイアログが表示されますので、アップロードするファイルを選択します。


ファイルのアップロードが始まります。メッセージラベルにはアップロードされたファイルのサイズが表示されプログレスバーにはアップロードの進行状況が表示されます。


アップロードが完了すると下図の画面になります。


以上でアップロードの進捗状況を表示するFlashによるアップロードアプリケーションが作成できました。
著者
iPentecのメインデザイナー
Webページ、Webクリエイティブのデザインを担当。PhotoshopやIllustratorの作業もする。
掲載日: 2012-03-22
iPentec all rights reserverd.