2015年11月9日月曜日

ASP.NETでファイルをダウンロードするボタン

クリックするとファイルをダウンロードするボタンを作りました。
主な機能は以下のとおりです。

  • クリックするとFileプロパティにセットされたファイルをダウンロードする
  • FileプロパティはClickイベントやDownloadingイベントでセットすることもできる
  • Downloadedイベントで動的に作成したファイルを削除することもできる
使用するには、以下の手順に従います。
  1. FileDownloadButtonをプロジェクトに追加する
  2. FileDownloadButtonをツールボックスへ追加する
    参考: 方法 : Visual Studio でカスタム ASP.NET サーバー コントロールを使用するの「カスタム コントロールをツールボックスに追加するには」
  3. *.aspxへFileDownloadButtonを配置し、イベントハンドラを設定する
    例:
    <cc1:FileDownloadButton ID="FileDownloadButton1" runat="server"
                            Text="Download"
                            OnDownloading="FileDownloadButton1_Downloading"
                            OnDownloaded="FileDownloadButton1_Downloaded"/>
    
  4. *.csでイベントハンドラを実装する
    例:
            protected void FileDownloadButton1_Downloading(object sender, EventArgs e)
            {
                // Tempファイルを作成する
                var path = Path.GetTempFileName();
                var file = new FileInfo(path);
    
                // Tempファイルへデータを出力する
                using (var s = file.OpenWrite())
                using (var w = new StreamWriter(s))
                {
                    w.WriteLine("Hello");
                    w.Flush();
                }
    
                // FileDownloadButtonのFileプロパティへTempファイルをセットする
                FileDownloadButton1.File = file;
            }
    
            protected void FileDownloadButton1_Downloaded(object sender, EventArgs e)
            {
                // Tempファイルを削除する
                FileDownloadButton1.File.Delete();
            }
    
Content-Typeの設定やレスポンスの呼び出しなど、低レベルな処理をカプセル化できるので、導入のメリットはそこそこあると思います。よろしければご利用ください。

以下、FileDownloadButtonのソースです。


using System;
using System.ComponentModel;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication1
{
    /// <summary>
    /// ファイルをダウンロードするボタン
    /// <para>m.yamamo0417@gmail.com</para>
    /// </summary>
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:FileDownloadButton runat=server></{0}:FileDownloadButton>")]
    public class FileDownloadButton : Button
    {
        /// <summary>
        /// Content-Type
        /// </summary>
        public const string ContentType = "application/octet-stream";

        private event EventHandler downloading;
        private event EventHandler downloaded;

        /// <summary>
        /// ダウンロード対象のファイル
        /// </summary>
        public FileInfo File { get; set; }

        /// <summary>
        /// ダウンロード開始前に発生するイベント
        /// </summary>
        [Browsable(true)]
        public event EventHandler Downloading
        {
            add    { downloading += value; }
            remove { downloading -= value; }
        }

        /// <summary>
        /// ダウンロード終了後に発生するイベント
        /// </summary>
        [Browsable(true)]
        public event EventHandler Downloaded
        {
            add    { downloaded += value; }
            remove { downloaded -= value; }
        }

        /// <summary>
        /// コンストラクタ
        /// <para>デフォルトのイベントハンドラをセット</para>
        /// </summary>
        public FileDownloadButton() : base()
        {
            downloading += (sender, e) => { };
            downloaded  += (sender, e) => { };
        }

        protected override void OnClick(EventArgs e)
        {
            // Clickイベントを発生させる
            base.OnClick(e);

            // Downloadingイベントを発生させる
            OnDownloading(e);

            // FileがnullのときはNullReferenceExceptionをthrowする
            if (File == null)
            {
                throw new NullReferenceException("Fileプロパティがnullです。");
            }

            // Fileが存在しないときはFileNotFoundExceptionをthrowする
            if (!File.Exists)
            {
                throw new FileNotFoundException("ファイルが見つかりません。", File.FullName);
            }

            // Content-Typeを設定
            Page.Response.ContentType = ContentType;

            // レスポンスへファイルの内容を出力する
            Page.Response.Clear();
            Page.Response.WriteFile(File.FullName);
            Page.Response.Flush();
            Page.Response.End();

            // Downloadedイベントを発生させる
            OnDownloaded(e);
        }

        /// <summary>
        /// Downloadingイベントを発生させる
        /// </summary>
        /// <param name="e">イベントオブジェクト</param>
        protected virtual void OnDownloading(EventArgs e)
        {
            downloading(this, e);
        }

        /// <summary>
        /// Downloadedイベントを発生させる
        /// </summary>
        /// <param name="e">イベントオブジェクト</param>
        protected virtual void OnDownloaded(EventArgs e)
        {
            downloaded(this, e);
        }
    }
}

0 件のコメント:

コメントを投稿