WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

SWFUpload を使ってみました

by WebSurfer 2010年11月3日 15:45
SWFUpload ライブラリを使ってみました

Flash を使って一度に複数ファイルをアップロードできる SWFUpload というライブラリを ASP.NET 環境下で試してみました。いろいろ分かったことがありますので、備忘録として Flash のクッキーがらみのバグなどの注意点を書いておきます。

複数ファイルを一度にアップロードしながらプログレスも表示できるという条件で、自分の期待を満たしそうなライブラリを探してみたところ、SWFUploadMultiple File Upload の 2 つが見つかりました。このうち、前者の SWFUpload を選んで試してみました。

なぜ SWFUpload の方を選んだかといえば、単に見た目が気に入ったからです。(笑) ただし、ASP.NET のコントロールのように Visual Studio の画面上でドラッグ&ドロップしてプロパティを設定するだけで使えるものではなく、ブラウザ側での操作にかなりの量の JavaScript のコードを書く必要があるのがちょっと重いです。でも、サンプルが提供されていますので、それをそのまま転用すればさほど面倒ではありません。

後者の Multiple File Upload の方は、ドキュメントを読んだ限りですが、ASP.NET 向けに特化されているようです。SWFUpload と同等な機能を ASP.NET のカスタムコントロールにラップして、ASP.NET に慣れたプログラマにとって使いやすくしているような感じです。

上の画像のアプリは、SWFUpload のサンプルの SimpleDemo と applicationdemo.net を合体して作ったものです。applicationdemo.net には、アップロードされた jpg ファイルからサーバー側のプログラムで Thumbnail を作って Session に保持し、クライアント側の JavaScript で動的に img タグを作ってそれに表示するコードが含まれています。

実際のアプリでは、Thumbnail を作って Session に保持する代わりに、サーバーのフォルダや DB に保存することになります。そのサンプルは提供されていませんが、従来の ASP.NET コントロールの FileUpload を使った場合と同等な処置となるので、ASP.NET アプリ開発経験者には簡単に実装できるはずです。

アプリの作り方を簡単に書いておきます。

ソリューションエクスプローラ
  1. Visual Studio で、新規に ASP.NET Web サイトプロジェクトを作ります。
  2. サンプルを Google のサイト からダウンロードします。現時点での最新版は SWFUpload v2.2.0.1 Samples.zip です。demos というフォルダの中に多数のサンプルが含まれています。
  3. demos\simpledemo フォルダの index.php が参照している .css, .js, .swf ファイルを使用しますので、適当なフォルダ(例: css, Scripts, Swfupload)をアプリケーションルート設けて、そこに参照されているファイルをコピーしてください。同名のファイルが複数含まれていますので、index.php が参照しているファイルのフォルダに注意してください。
  4. handlers.js に Thumbnail 書き込みのための JavaScript コードを追加します。上の手順でコピーした handlers.js を Visual Studio で開き、そこに demos\applicationdemo.net\js\handlers.js の addImage, fadeIn メソッドを丸ごとコピーします。さらに、uploadSuccess メソッドに addImage("thumbnail.aspx?id=" + serverData); を追加します。下の例を参考にしてください。
  5. アプリケーションルートに demos\applicationdemo.net フォルダの Global.asax, thumbnail.aspx, thumbnail.aspx.cs, upload.aspx, upload.aspx.cs をコピーしてください。
  6. アプリケーションルートに App_Code フォルダを作成し、demos\applicationdemo.net\App_Code フォルダの Thumbnail.cs をコピーしてください。
  7. アプリケーションルートに images フォルダを作成し、demos\images, demos\simpledemo\images, demos\applicationdemo.net\images フォルダの画像ファイルをコピーしてください。default.css を開いて、画像の url(3 ヶ所あります)を修正してください。
  8. Default.aspx, Default.aspx.cs, web.config は、ASP.NET の Web サイトプロジェクトを作った際に自動生成されたものに手を加えて使用します。ここまでで Web サイトプロジェクトの構成は上のソリューションエクスプローラの画像のようになっているはずです。
  9. 大きなファイルをアップロードする場合は、web.config に httpRuntime 要素の設定変更が必要です。設定例は、samples\asp.net フォルダの web.config にあります。加えて、IIS7 では applicationHost.config の requestFiltering 要素の設定も要注意です。
  10. 続いて、Deafult.aspx.cs の Page_Load イベントハンドラに Session.Clear(); を追加します。
  11. Deafult.aspx に index.php のコードを移植します。その際、 Flash のパラメータ flash_url, post_params を修正し、Thumbnail 画像を格納する div タグを追加します。ヘッダーのロゴのリンク先も適宜変更してください。下の例を参考にしてください。

handler.js(一部のみ)

function uploadSuccess(file, serverData) {
  try {
    // この行追加
    addImage("thumbnail.aspx?id=" + serverData);

    var progress = 
      new FileProgress(file, this.customSettings.progressTarget);
    progress.setComplete();
    progress.setStatus("Complete.");
    progress.toggleCancel(false);
  } catch (ex) {
    this.debug(ex);
  }
}

// 以下の function 2 つを追加
function addImage(src) {
  var newImg = document.createElement("img");
  newImg.style.margin = "5px";
  ・・・中略・・・
}

function fadeIn(element, opacity) {
  var reduceOpacityBy = 5;
  var rate = 30; // 15 fps
  ・・・中略・・・
}

Default.aspx.cs

public partial class _Default : System.Web.UI.Page 
{
  protected void Page_Load(object sender, EventArgs e)
  {
    // Clear the user's session
    Session.Clear();
  }
}

Default.aspx

<%@ Page Language="C#" 
  AutoEventWireup="true"  
  CodeFile="Default.aspx.cs" 
  Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>SWFUpload Demos - Simple Demo</title>
  <link href="css/default.css" rel="stylesheet" type="text/css" />
  <script src="Swfupload/swfupload.js" type="text/javascript"></script>
  <script src="Scripts/swfupload.queue.js" type="text/javascript"></script>
  <script src="Scripts/fileprogress.js" type="text/javascript"></script>
  <script src="Scripts/handlers.js" type="text/javascript"></script>
  <script type="text/javascript">
  var swfu;

  window.onload = function() {
    var settings = {
      flash_url: "swfupload/swfupload.swf",

      // アップロードされたファイルをサーバーで保存するなどの
      // 処置(このサンプルでは Thumbnail の表示)を行うページ
      // を指定する。
      upload_url: "upload.aspx",

      // Flash のバグによるセッション切れ、Forms 認証切れ問題
      // の対応。セッションクッキーと Forms 認証クッキーを、そ
      // れぞれ ASPSESSID, AUTHID という名前でフォームに含めて
      // 送信する。Global.asax の BeginRequest ハンドラでそれら
      // を取得して、応答クッキーを書き換える。
      post_params: {
        "ASPSESSID": "<%=Session.SessionID %>",
        "AUTHID": "<%=Request.Cookies[FormsAuthentication.FormsCookieName] == null? String.Empty : Request.Cookies[FormsAuthentication.FormsCookieName].Value %>" 
      },
      file_size_limit: "100 MB",
      file_types: "*.*",
      file_types_description: "All Files",
      file_upload_limit: 100,
      file_queue_limit: 0,
      custom_settings: {
        progressTarget: "fsUploadProgress",
        cancelButtonId: "btnCancel"
      },
      debug: false,

      // Button settings
      button_image_url: "images/TestImageNoText_65x29.png",
      button_width: "65",
      button_height: "29",
      button_placeholder_id: "spanButtonPlaceHolder",
      button_text: '<span class="theFont">Hello</span>',
      button_text_style: ".theFont { font-size: 16; }",
      button_text_left_padding: 12,
      button_text_top_padding: 3,

      // The event handler functions are defined in handlers.js
      file_queued_handler: fileQueued,
      file_queue_error_handler: fileQueueError,
      file_dialog_complete_handler: fileDialogComplete,
      upload_start_handler: uploadStart,
      upload_progress_handler: uploadProgress,
      upload_error_handler: uploadError,
      upload_success_handler: uploadSuccess,
      upload_complete_handler: uploadComplete,

      // Queue plugin event
      queue_complete_handler: queueComplete
    };

    swfu = new SWFUpload(settings);
  };
  </script>
</head>
<body>
  <form id="form1" runat="server">
    <div id="header">
      <h1 id="logo"><a href="index.html">SWFUpload</a></h1>
      <div id="version">v2.2.0</div>
    </div>
    <div id="content">
      <h2>Simple Demo</h2>
      <p>This page demonstrates a simple usage of SWFUpload.  
         It uses the Queue Plugin to simplify uploading or 
         cancelling all queued files.</p>
      <div class="fieldset flash" id="fsUploadProgress">
        <span class="legend">Upload Queue</span>
      </div>
      <div id="divStatus">0 Files Uploaded</div>
      <div>
        <span id="spanButtonPlaceHolder"></span>
        <input id="btnCancel" 
          type="button" 
          value="Cancel All Uploads" 
          onclick="swfu.cancelQueue();" 
          disabled="disabled" 
          style="margin-left: 2px; font-size: 8pt; height: 29px;" />
        <%--Thumbnail 画像表示のため追加--%>
        <div id="thumbnails"></div>
      </div>   
    </div>
  </form>
</body>
</html>

以上で Web アプリは動くはずです。[Hello]ボタンをクリックするとファイルの選択ダイアログが開くので、jpg ファイルを選択して(複数選択可)、ダイアログの[開く(O)]ボタンをクリックすれば選択したファイルがアップロードされ、upload.aspx で処置されて、上の画像のような Thumbnail が表示されます。

問題の Flash のバグの話を以下に書きます。Firefox, Chrome, Safari など、IE 以外のブラウザを使用した場合は Flash がページを要求する際、クッキーが送られないという問題があります。

Flash が起動されている状態でも、HyperLink クリックでページを要求した場合や、ブラウザのアドレスバーに URL を打ち込んで要求する場合はクッキーは送られます。問題は、あくまで Flash がページを要求する場合ということに注意してください。今回の例では、Flash が flash_url パラメータに設定されている upload.aspx を要求する場合がそれに該当します。

当然ながら、クッキーが送られないとセッションが維持できません。今回の例では、Session に Thumbnail 画像を保持しているので、要求にクッキーが含まれないとセッションが維持できず、アップロード後に画像の Thumbnail を表示するところがうまくいきません。

ファイルがアップロードされると、Flash はパラメータ upload_url で指定されている upload.aspx を自動的に要求しますが、このときクッキーは送信されません。それ故、サーバー側で正しく Session が取得できず、別の Session に Thumbnail を書き込んでしまいます。結果、Thumbnail 画像は表示されません。

回避策は、post_params に "ASPSESSID": "<%=Session.SessionID %>" を設定し(こうすることにより、ブラウザはフォーム変数にセッション ID を含めて送信します)、Global.asax の BeginRequest イベントのハンドラでフォーム変数からセッション ID を取得し、それでクッキーを書き換えてやることです。

いままで作成したコードに回避策が折り込み済みです。なので、Thumbnail は問題なく表示されます。Default.aspx の post_params の設定と、Global.asax の BeginRequest ハンドラを見てください。

Forms 認証を行う場合も、同様に、Flash のバグによる認証クッキー切れの問題があります。

例えば、Forms 認証を設定し、login.aspx ページを設け、ルートの web.config で deny user="?" として全ページ(upload.aspx を含め)匿名アクセス不可とした場合を考えます。ログインすれば Default.aspx は表示され、アップロードするファイルを選択するところまでは行きます。ところが、いざアップロードしようとすると HTTP 302 が返されてアップロードに失敗します。これは、Flash が upload.aspx を要求したとき、認証クッキーが送られてこないので、login.aspx にリダイレクトされてしまうからです。

この問題は、セッションクッキーの場合と同様な方法で、post_params で認証クッキーをフォーム変数に含めて送るように設定し、Global.asax の BeginRequest ハンドラで認証クッキーを書き換えることで回避できます。この回避策もいままで作成したコードに折り込み済みです。

Default.aspx の post_params の設定と、Global.asax の BeginRequest ハンドラを見てください。この対応で、Flash のバグによるセッションクッキーと Forms 認証クッキーが切れる問題は回避でき、ASP.NET 環境で SWFUpload を使えるようになるはずです。

なお、くどいようですが、Flash のバグによるクッキー切れの問題は、Firefox, Chrome, Safari など、IE 以外のブラウザを使用した場合のみですので注意してください。

Tags: , ,

Upload Download

コメント

2012年9月3日 10:39   #

MoeYamamoto

とてもわかりやすい説明でソースを真似て作成しました。
IE7,8ではうまくいきました。
ここ最近IE9を導入しましたら、うまく動かなくなってしまいました。
IE9の場合、パラメータの設定が異なるのでしょうか。
もし、解決済みでありましたら、ご教示いただけますと幸いです。
よろしくお願いいたします。

MoeYamamoto 日本

2012年9月3日 20:48   #

websurfer

MoeYamamoto さん、こんにちは

IE7, 8 ではうまくいったが IE9 では動かなくなってしまったそうですが、自分の環境では IE9 で問題なく動きます。IE のバージョンで変わる要素は何もないはずですが・・・

すみませんが、書かれている情報だけでは何が問題なのか分かりません。

websurfer 日本

2012年9月27日 13:04   #

MoeYamamoto

お返事をありがとうございます。
開発環境は、Visual Studio 2010 asp.net4.0です。
ブラウザのバージョンをIE8から、IE9に上げると、アップロードのボタン「select images ...」が表示されなくなります。
そちらでうまく動作しているIE9の開発環境は、どのようなものでしょうか。
PHPでは、IE9でも問題ないようです。

ソース自体は、demoのソースをそのまま使用し、参照している各ファイルの値を変更した程度です。

どうぞ、よろしくお願いいたします。

MoeYamamoto 日本

2012年9月27日 22:03   #

websurfer

MoeYamamoto さん、こんにちは。

前にも書きましたが、IE のバージョンで変わる要素は何もないはずです。Flash Player の違いは可能性としてはあるかもしれません。念のためチェックしてみてください。

なお、"アップロードのボタン「select images ...」" とのことですが、当方のブログに書いてあるとおり作ったのなら、そのような名前にはならないです。ブログの画像(クリックすると拡大画面が表示されます)を見てください。同じものではないのでは?

ちなみに、当方が確認した時の環境は IE9(バージョン: 9.0.8112.16421、更新バージョン: 9.0.10 (KB2744842))、Vista Ultimate SP2、IIS7、ASP.NET 3.5、Flash Player 11.4.402.265、Visual Studio 2010 pro です。

websurfer 日本

2012年9月28日 11:45   #

Moe

早々のお返事をありがとうございます。
Flash Playerのバージョンを確認しました。
ActiveXのバージョン:11.3.300.268となっていましたので、最新バージョン11.4.402.275にアップグレードしましたが、結果は同じでした。

また、ご指摘の通り、アップロードボタンの文字列は変更しており、現在は、全く同じソースにしております。
したがって、
images/TestImageNoText_65x29.png
文字列は、「Hello」となるかと思います。

同ソースを別の機器(Windows7 IE8 FlashPlayer11.4.402.265 iis7 ASP.NET 4.0)で確認しますと、問題なくアップロードボタン「Hello」が表示され、ファイルをアップすることが可能です。

ブラウザをIE8からIE9(バージョン: 9.0.8112.16421、更新バージョン: 9.0.10 (KB2744842))、にアップデートした機器は、それまで表示されていたアップロードボタンが表示されません。

こちらでは、ブラウザのバージョンの違いとの認識でおりますが、
そちらでは、問題ないとのことですので、ブラウザのバージョンを元に戻せば解決できるのですが、後退することは避けたいと思い、おたずねした次第です。

今一度、ソースを確認してみたいと思います。

Moe 日本

2012年9月28日 12:18   #

Moe

先程、FlashPlayerのバージョンをアップ後、現状は変わらないとの連絡を致しましたが、
ブラウザを再起動を怠っていたみたいです。
アップロードボタンが表示されることを確認いたしました。
お手数をおかけいたしまして申し訳ありませんでした。

Moe 日本

2012年9月28日 13:29   #

Moe

先程、慌てて訂正の連絡を行いましたが、
IE9でもcompatibleモードの時のみ表示できるというのが正しいようです。
互換設定の切り替えでボタンが表示される、されないというところまでわかりましたので、
再度このあたりから、調べてみたいと思います。

何度も連絡を行いまして申し訳ありませんでした。

Moe 日本

2012年9月28日 22:12   #

websurfer

MoeYamamoto さん、こんにちは。

[Hello]ボタンは Flash で表示されるので(開発者ツールで見てください)、表示されないということは Flash が起動できていないということのようです。

ただし、当方で試した限り、IE9 の互換/標準モードの違いは[Hello]ボタンの表示には影響ありませんでした(互換/標準モードどちらでも[Hello]ボタンは表示され、動作も正常です)。

何が違うんでしょうね。

websurfer 日本

2012年10月1日 15:42   #

Moe

お返事をありがとうございます。
そちらでは、何れのモードでも問題なく表示されるとのこと、了解しました。
もう少し、確認してみます。

Moe 日本

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar