最近のトラックバック

2017年9月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

Google AdSense2

« 2009年5月 | トップページ | 2009年7月 »

2009年6月

ASP.NET(C#)でファイルダウンロード

ASP.NET(C#)でファイルダウンロードのサンプルコードを作成してみた。



ダウンロード処理のメインソースは以下の通り

// Response情報クリア
Response.ClearContent();
// HTTPヘッダー情報設定
Response.AddHeader("Content-Disposition", "attachment;filename=①ファイル名");
Response.ContentType = ②MIME;
// ファイル書込(データによりResponse.WriteFile()、Response.Write()、Response.BinaryWrite()を使い分ける。)
Response.WriteFile(sFilePath);
// レスポンス終了
Response.End();


上記ソースのうち「①ファイル名」と「②MIME」に関しては注意が必要である。

■①ファイル名について
ファイル名に日本語が含まれる場合、IEとIE以外のブラウザで挙動が異なるため注意する必要がある。
日本語を含むファイル名はIE以外のブラウザの場合は問題ないが、IEの場合ファイルダウンロードダイアログで文字化けを起こす。
このためブラウザがIEの場合、URLエンコードをする必要がある。

HttpUtility.UrlEncode(sFileName)


■②MIME
Response.ContentTypeにはファイル形式毎にコンテンツタイプを指定する必要がある。

拡張子とMIMEタイプ - とほほのWWW入門では、 MIMEを以下のように説明している。
Webの世界では拡張子という概念と、もうひとつ『MIMEタイプ』という概念があります。MIMEタイプとは「タイプ名/サブタイプ名」の形式の文字列で、WEBサーバーとWEBブラウザの間はこのMIMEタイプを用いてデータの形式を指定しています。

MIMEの一例を挙げると次の通り。
ファイル形式 一般的な拡張子 MIMEタイプ
テキストファイル .txt text/plain
HTML .htm,.html text/html
CSVファイル .csv text/comma-separated-values
TSVファイル .txt, .tsv text/tab-separated-values
XMLファイル .xml text/xml
Microsoft Wordファイル .doc, .docx application/msword
Microsoft Excelファイル .xls, xlsx application/msexcel
Microsoft PowerPointファイル .ppt, pptx application/mspowerpoint
PDFファイル .pdf application/pdf
ビットマップファイル .bmp image/bmp
GIFファイル .gif image/gif
JPEGファイル .jpg image/jpeg
PNGファイル.png .png image/png
ZIPファイル .zip application/zip
LZHファイル .lzh application/lha
スタイルシートファイル .css text/css
JavaScriptファイル .js text/javascript
VBScriptファイル .vbs text/vbscript
実行ファイル .exe application/octet-stream

参考:MIMEタイプ一覧


ファイルダウンロードのサンプルソースを記述する。

実行結果及びASP.NETソースコードの確認
 :
 :
<script runat="server">
    /// <summary>
    /// テキストファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnTxt_Click(object sender, EventArgs e)
    {
        fnDownloadFile("テキストファイル.txt", "text/plain");
    }
    /// <summary>
    /// HTMLファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnHtm_Click(object sender, EventArgs e)
    {
        fnDownloadFile("HTMLファイル.htm", "text/html");
    }
    /// <summary>
    /// CSVファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnCsv_Click(object sender, EventArgs e)
    {
        fnDownloadFile("CSVファイル.csv", "text/comma-separated-values");
    }
    /// <summary>
    /// TSVファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnTsv_Click(object sender, EventArgs e)
    {
        fnDownloadFile("TSVファイル.txt", "text/tab-separated-values");
    }
    /// <summary>
    /// XMLファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnXml_Click(object sender, EventArgs e)
    {
        fnDownloadFile("XMLファイル.xml", "text/xml");
    }
    /// <summary>
    /// Wordファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnDoc_Click(object sender, EventArgs e)
    {
        fnDownloadFile("Wordファイル.doc", "application/msword");
    }
    /// <summary>
    /// Excelファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnXls_Click(object sender, EventArgs e)
    {
        fnDownloadFile("Excelファイル.xls", "application/msexcel");
    }
    /// <summary>
    /// PowerPointファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnPpt_Click(object sender, EventArgs e)
    {
        fnDownloadFile("PowerPointファイル.ppt", "application/mspowerpoint");
    }
    /// <summary>
    /// PDFファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnPdf_Click(object sender, EventArgs e)
    {
        fnDownloadFile("PDFファイル.pdf", "application/pdf");
    }
    /// <summary>
    /// ビットマップファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnBmp_Click(object sender, EventArgs e)
    {
        fnDownloadFile("ビットマップファイル.bmp", "image/bmp");
    }
    /// <summary>
    /// GIFファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnGif_Click(object sender, EventArgs e)
    {
        fnDownloadFile("GIFファイル.gif", "image/gif");
    }
    /// <summary>
    /// JPEGファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnJpg_Click(object sender, EventArgs e)
    {
        fnDownloadFile("JPEGファイル.jpg", "image/jpeg");
    }
    /// <summary>
    /// PNGファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnPng_Click(object sender, EventArgs e)
    {
        fnDownloadFile("PNGファイル.png", "image/png");
    }
    /// <summary>
    /// ZIPファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnZip_Click(object sender, EventArgs e)
    {
        //fnDownloadFile("ZIPファイル.zip", "application/zip"); // MIMEを指定すると動かない場合がある
        fnDownloadFile("ZIPファイル.zip", "");
    }
    /// <summary>
    /// LZHファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnLzh_Click(object sender, EventArgs e)
    {
        fnDownloadFile("LZHファイル.lzh", "application/lha");
    }
    /// <summary>
    /// スタイルシートファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnCss_Click(object sender, EventArgs e)
    {
        fnDownloadFile("スタイルシートファイル.css", "text/css");
    }
    /// <summary>
    /// JavaScriptファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnJs_Click(object sender, EventArgs e)
    {
        fnDownloadFile("JavaScriptファイル.js", "text/javascript");
    }
    /// <summary>
    /// VBScriptファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnVbs_Click(object sender, EventArgs e)
    {
        fnDownloadFile("VBScriptファイル.vbs", "text/vbscript");
    }
    /// <summary>
    /// 実行ファイルダウンロード
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnExe_Click(object sender, EventArgs e)
    {
        fnDownloadFile("実行ファイル.exe", "application/octet-stream");
    }
    /// <summary>
    /// ファイルダウンロード
    /// </summary>
    /// <param name="sFileName"></param>
    /// <param name="sMIME"></param>
    public void fnDownloadFile(string sFileName, string sMIME)
    {
        string sFilePath;           // ファイルパス
        string sDownloadFileName;   // ダウンロードファイル名
        //-----------------------------------------------------------------------------------------
        // 物理ファイルパス取得
        //-----------------------------------------------------------------------------------------
        sFilePath = MapPath(string.Format(@"./File/{0}", sFileName));
        //-----------------------------------------------------------------------------------------
        // 日本語ファイル名を考慮したダウンロードファイル名作成
        //-----------------------------------------------------------------------------------------
        if (Request.Browser.Browser == "IE")
        {
            // IEの場合、ファイル名をURLエンコード
            sDownloadFileName = HttpUtility.UrlEncode(sFileName);
        }
        else
        {
            // IE以外はファイル名は無加工
            sDownloadFileName = sFileName;
        }
        //-----------------------------------------------------------------------------------------
        // ダウンロード処理
        //-----------------------------------------------------------------------------------------
        // Response情報クリア
        Response.ClearContent();
        // バッファリング
        Response.Buffer = true;
        // HTTPヘッダー情報設定
        Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", sDownloadFileName));
        Response.ContentType = sMIME;
        // ファイル書込
        Response.WriteFile(sFilePath);
        // フラッシュ
        Response.Flush();
        // レスポンス終了
        Response.End();
    }
</script>
<h1>ファイルダウンロード</h1>
<!-- コンテンツ説明 -->
<div class="contents_info">
    ASP.NETからファイルをダウンロードするサンプルです。<br />
</div>
<!-- コンテンツ -->
<asp:Button ID="btnTxt" runat="server" Text="テキストファイルダウンロード"  onclick="btnTxt_Click" /><br />
<asp:Button ID="btnHtm" runat="server" Text="HTMLファイルダウンロード"  onclick="btnHtm_Click" /><br />
<asp:Button ID="btnXml" runat="server" Text="Xmlファイルのダウンロード"  onclick="btnXml_Click" /><br />
<asp:Button ID="btnCsv" runat="server" Text="CSVファイルダウンロード" onclick="btnCsv_Click" /><br />
<asp:Button ID="btnTsv" runat="server" Text="TSVファイルダウンロード" onclick="btnTsv_Click" /><br />
<asp:Button ID="btnDoc" runat="server" Text="Wordファイルダウンロード" onclick="btnDoc_Click" /><br />
<asp:Button ID="btnXls" runat="server" Text="Excelファイルダウンロード" onclick="btnXls_Click" /><br />
<asp:Button ID="btnPpt" runat="server" Text="PowerPointファイルダウンロード" onclick="btnPpt_Click" /><br />
<asp:Button ID="btnPdf" runat="server" Text="PDFファイルダウンロード"  onclick="btnPdf_Click" /><br />
<asp:Button ID="btnBmp" runat="server" Text="ビットマップファイルダウンロード" onclick="btnBmp_Click" /><br />
<asp:Button ID="btnGif" runat="server" Text="GIFファイルダウンロード"  onclick="btnGif_Click" /><br />
<asp:Button ID="btnJpg" runat="server" Text="JPEGファイルダウンロード" onclick="btnJpg_Click" /><br />
<asp:Button ID="btnPng" runat="server" Text="PNGファイルダウンロード" onclick="btnPng_Click" /><br />
<asp:Button ID="btnZip" runat="server" Text="ZIPファイルダウンロード" onclick="btnZip_Click" /><br />
<asp:Button ID="btnLzh" runat="server" Text="LZHファイルダウンロード" onclick="btnLzh_Click" /><br />
<asp:Button ID="btnCss" runat="server" Text="スタイルシート(CSS)ファイルダウンロード" onclick="btnCss_Click" /><br />
<asp:Button ID="btnVbs" runat="server" Text="VBScriptファイルダウンロード" onclick="btnVbs_Click" /><br />
<asp:Button ID="btnJs"  runat="server" Text="JavaScriptファイルダウンロード" onclick="btnJs_Click" /><br />
<asp:Button ID="btnExe" runat="server" Text="実行ファイルダウンロード" onclick="btnExe_Click" /><br />
<br />
 :
 :


  • ASP.NET(C#)でファイルダウンロードしながら画面更新
  • ASP.NET(C#)でバイナリファイルをブラウザ表示
  • ASP.NET(C#)でIEにOfficeドキュメントを表示
  • ASP.NET(C#)でIEのファイルダウンロードダイアログボタンをカスタマイズ

  • 拡張子とMIMEタイプ - とほほのWWW入門
  • MIMEタイプ一覧
  • 方法 : ASP.NET Web ページでブラウザの種類を検出する

  • C#でCSV・TSVファイル作成

    C#でDataTableからCSVファイルまたはTSVファイルを作成してみた。



    「データをカンマで区切り、改行で1レコード」という条件ででDataTableからCSVファイルを作るサンプルコード。

    実行結果及びASP.NETソースコードの確認
    
    
    //-------------------------------------------------------------------------------------
    // データ作成
    //-------------------------------------------------------------------------------------
    DataTable dtData = new DataTable();
    // 列作成
    dtData.Columns.Add("colInt32", typeof(Int32));
    dtData.Columns.Add("colInt64", typeof(Int64));
    dtData.Columns.Add("colDouble", typeof(Double));
    dtData.Columns.Add("colDecimal", typeof(Decimal));
    dtData.Columns.Add("colNull", typeof(Int32));
    dtData.Columns.Add("colDateTime", typeof(DateTime));
    dtData.Columns.Add("colBoolean", typeof(Boolean));
    dtData.Columns.Add("colString", typeof(String));
    // データ投入
    for (int i = 1; i <= 5; i++)
    {
        DataRow dr = dtData.NewRow();
        dr["colInt32"] = i;
        dr["colInt64"] = i * i;
        dr["colDouble"] = 1.1 * i;
        dr["colDecimal"] = 10.1 * i;
        dr["colNull"] = DBNull.Value;
        dr["colDateTime"] = new DateTime(2010, 1, i);
        dr["colBoolean"] = (i % 2 == 0) ? true : false;
        dr["colString"] = string.Format("文字列{0}", (char)('A' + i - 1));
        dtData.Rows.Add(dr);
    }
    //-----------------------------------------------------------------------------------------
    // CSVファイル作成
    //-----------------------------------------------------------------------------------------
    // 一時ファイル作成
    string sTempFilePath = Path.GetTempFileName();
    // CSVファイル書込
    using (StreamWriter sw = new StreamWriter(sTempFilePath, false, Encoding.GetEncoding("Shift-JIS")))
    {
        // 行列ループ
        for (int iRow = 0; iRow < dtData.Rows.Count; iRow++)
        {
            string sRecord = "";  // レコード
            // 1レコード作成
            for (int iCol = 0; iCol < dtData.Columns.Count; iCol++)
            {
                sRecord += string.Format("{0},", dtData.Rows[iRow][iCol]);
            }
            // 行末のカンマを削除
            sRecord = sRecord.Remove(sRecord.Length - 1, 1);
            // ファイル書込
            sw.WriteLine(sRecord);
        }
        // ファイルクローズ
        sw.Close();
    }
    

    上記ソースで作成されるCSVファイルの内容


    大概は上記サンプルでも通用することが多いが、CSVとしては以下の問題がある。
    • データにカンマ、改行を含む文字列がある場合に正しく処理できない。
    • 空文字とnull文字の判定ができない。
    • Byte配列、Byte型、SByte型等の文字列変換が困難なデータ型を文字変換すると予期せぬ文字列を返す。

    PS. DataTableに格納できる基本データ型
    • Boolean
    • Byte
    • Char
    • DateTime
    • Decimal
    • Double
    • Int16
    • Int32
    • Int64
    • SByte
    • Single
    • String
    • TimeSpan
    • UInt16
    • UInt32
    • UInt64
    • Byte[]
    参考:DataColumn.DataType プロパティ

    また使い勝手として以下が考えられる。
    • CSV(カンマ区切り)でなく、TSV(タブ区切り)を指定したい。
    • 文字コードはShift-JIS以外を指定したい。
    • 改行文字はCRLF・CR・LFのいずれかを指定したい。
    • ヘッダ行を出力有無を指定したい。
    • 最終行に改行文字が出力有無を指定したい。
    • Boolean型の出力書式は、True/Falseでなく1/0を指定したい。。
    • DateTime型の出力書式は「YYYY/MM/DD HH:mm:ss」「YYYYMMDD」等の時間書式を指定したい。


    CSVファイルはRFC 4180で国際規格化されている。
    しかしRFC 4180は現行仕様の追認形式をとっているため仕様が厳格な規格ではない。

    Comma-Separated Values - Wikipediaを参考にRFC 4180をまとめると以下の通り。
    • ファイルは1つ以上のレコードからなる。レコードは改行で区切られる。最後のレコードの後には改行はあってもなくてもいい。
    • レコードは1つ以上の同じ個数のフィールドからなる。フィールドはコンマ「,」で区切られる。最後のフィールドの後にはコンマは付けない。
    • 1,2,となっている場合は3列目はnull文字を表す
    • ファイルの先頭には、オプションとして、通常のレコードと同一の書式の「ヘッダ行」があってもいい。ヘッダ行は、他のレコードと同じ個数のフィールドを持ち、フィールドの名称が書かれている。
    • フィールドは、ダブルクォート「"」で囲んでも囲まなくてもよい。
    • フィールドがコンマ、ダブルクォート、改行を含む場合は、かならずダブルクォートで囲む。また、フィールドに含まれるダブルクォートは2つ並べてエスケープする。


    これまでの条件を満たし規格や使い勝手を考慮したDataTableからCSV/TSVファイルを作成するサンプルソース(DataTable2CharacterSeparatedValuesクラス)を記述する。

    サンプルソースのpublicメソッドは以下の通り。
    メソッド名 シグニチャ 概要
    テキストデータファイル作成 DataTable2CharacterSeparatedValues.CreateFile
    (
      DataTable dtData,
      string sDustFilePath,
      Option opt
    )
    CSV/TSVファイルの作成。
    引数は以下の通り
    dtData 出力対象のDataTable
    sDustFilePath 出力ファイルパス
    opt オプション(後述)

    上記メソッドの第3引数のOptionクラスのフィールドは以下の通り。
    フィールド シグニチャ 既定値 概要
    文字コード Encoding enc Shift-JIS ファイルの文字コードを指定。
    フィールド区切り文字 string sFiledSeparator カンマ(,) フィールド区切り文字を指定。
    行区切り文字 string sLineBreak CRLF 行区切り文字を指定。
    フィールド囲み enumFieldEnclosed enFieldEnclosed 特殊文字列を含む文字列フィールドだけ囲む フィールドをダブルクォーテーション(")で囲むか指定。
    ヘッダ行の出力有無 bool bOutputHeader false ヘッダ行の出力するか指定。
    ヘッダ行の列名は引数dtDataのDataColumns[n].ColumnName。
    最終レコードに行区切り文字挿入 bool bLastRecordLineBreak true 最終レコードに行区切り文字を挿入するか指定。
    Boolean型の出力書式 bool bBooleanTypeFormat true Boolean型の出力書式を指定。
    trueの場合、True/Falseで出力。
    falseの場合、1/0で出力。
    DateTime型の出力書式 string sDateTimeTypeFormat yyyyMMdd HH:mm:ss DateTime型の出力書式を指定。
    出力書式はDateTime.ToString()と同じ書式。

    実行結果及びASP.NETソースコードの確認
    
    
    using System;
    using System.IO;
    using System.Data;
    using System.Text;
    
    /// <summary>
    /// DataTableからテキストファイル(CSV/TSV)作成クラス
    /// </summary>
    public class DataTable2CharacterSeparatedValues
    {
        /// <summary>
        /// フィールド囲み
        /// </summary>
        public enum enumFieldEnclosed
        {
            None,                               // フィールドを囲まない
            AllField,                           // 全フィールドを囲む
            StringField,                        // 文字列フィールドだけ囲む
            ContainingSpecialCharactersField    // 特殊文字列を含む文字列フィールドだけ囲む
        }
        /// <summary>
        /// オプション
        /// </summary>
        public class Option
        {
            /// <summary>
            /// 文字コード
            /// </summary>
            public Encoding enc = Encoding.GetEncoding("Shift-JIS");
            /// <summary>
            /// フィールド区切り文字
            /// </summary>
            public string sFiledSeparator = ",";
            /// <summary>
            /// 行区切り文字
            /// </summary>
            public string sLineBreak = "\r\n";
            /// <summary>
            /// フィールド囲み
            /// </summary>
            public enumFieldEnclosed enFieldEnclosed = enumFieldEnclosed.ContainingSpecialCharactersField;
            /// <summary>
            /// ヘッダ行の出力有無
            /// </summary>
            public bool bOutputHeader = true;
            /// <summary>
            /// 最終レコードに行区切り文字挿入
            /// </summary>
            public bool bLastRecordLineBreak = true;
            /// <summary>
            /// Boolean型の出力書式(trueでTrue/False、falseで'1'/'0'と出力)
            /// </summary>
            public bool bBooleanTypeFormat = true;
            /// <summary>
            /// DateTime型の出力書式
            /// </summary>
            public string sDateTimeTypeFormat = "yyyyMMdd HH:mm:ss";
        }
        /// <summary>
        /// テキストデータファイル作成
        /// </summary>
        /// <param name="dtData">出力対象のDataTable</param>
        /// <param name="sDustFilePath">出力ファイルパス</param>
        /// <param name="opt">
        /// オプション(DataTable2TextFile.Optionクラス)
        /// enc                 : 文字コード            既定:Shift-JIS
        /// sFiledSeparator     : フィールド区切り      既定:カンマ(,)
        /// sLineBreak          : 行区切り              既定:CRLF
        /// enFieldEnclosed     : フィールド囲み        既定:特殊文字列を含む文字列フィールドだけ囲む
        /// bOutputHeader       : ヘッダ行の出力有無    既定:false
        /// bBooleanTypeFormat  : DateTime型の出力書式  既定:true(yyyyMMdd HH:mm:ss)
        /// sDateTimeTypeFormat : DateTime型の出力書式  既定:true(yyyyMMdd HH:mm:ss)
        /// </param>
        public static void CreateFile(DataTable dtData, string sDustFilePath, Option opt)
        {
            StringBuilder sbContents = new StringBuilder(1024); // ファイルコンテンツ
            string sFieldEnclosed;                              // フィールド囲み文字
            //-----------------------------------------------------------------------------------------
            // データ型チェック
            //-----------------------------------------------------------------------------------------
            foreach (DataColumn col in dtData.Columns)
            {
                // データ型取得
                Type type = col.DataType;
                // 配列型チェック(Byte[]向け)
                // ※バイト配列型は印字不可能な文字になるかもしれないので削除
                if (type.IsArray)
                {
                    throw new ApplicationException("配列はフィールドに設定できません");
                }
                // バイト型(Byte/SByte)チェック
                // ※バイト型は印字不可能な文字になるかもしれないので削除
                if (type == typeof(Byte) || type == typeof(SByte))
                {
                    throw new ApplicationException("バイト型はフィールドに設定できません");
                }
            }
            //-----------------------------------------------------------------------------------------
            // フィールド囲み文字
            //-----------------------------------------------------------------------------------------
            // 「全フィールドを囲む」の場合
            if (opt.enFieldEnclosed == enumFieldEnclosed.AllField)
            {
                sFieldEnclosed = "\"";
            }
            // 「フィールドを囲まない」
            // 「文字列フィールドだけ囲む」
            // 「特殊文字列を含む文字列フィールドだけ囲む」の場合
            else
            {
                sFieldEnclosed = "";
            }
            //-----------------------------------------------------------------------------------------
            // ヘッダ行作成
            //-----------------------------------------------------------------------------------------
            if (opt.bOutputHeader)
            {
                // 列名作成
                foreach (DataColumn col in dtData.Columns)
                {
                    sbContents.Append(col.ColumnName);
                    sbContents.Append(opt.sFiledSeparator);
                }
                // 最後のフィールド区切りを削除
                if (sbContents.Length > 0)
                {
                    sbContents.Remove(sbContents.Length - opt.sFiledSeparator.Length, opt.sFiledSeparator.Length);
                }
                // 行区切り挿入
                sbContents.Append(opt.sLineBreak);
            }
            //-----------------------------------------------------------------------------------------
            // コンテンツ行作成
            //-----------------------------------------------------------------------------------------
            for (int iRow = 0; iRow < dtData.Rows.Count; iRow++)
            {
                // 列データ作成
                for (int iCol = 0; iCol < dtData.Columns.Count; iCol++)
                {
                    // フィールドデータ取得
                    object objField = dtData.Rows[iRow][iCol];
                    // NULLの場合
                    if (objField is DBNull)
                    {
                        sbContents.Append(opt.sFiledSeparator);
                    }
                    // 文字(String/Char)の場合
                    else if (objField is String || objField is Char)
                    {
                        string sField = objField.ToString();
                        switch(opt.enFieldEnclosed)
                        {
                            //「フィールドを囲まない」
                            case enumFieldEnclosed.None:
                                sbContents.Append(sField);
                                break;
                            //「全フィールドを囲む」の場合
                            case enumFieldEnclosed.AllField:
                                sField = sField.Replace("\"", "\"\"");
                                sbContents.AppendFormat("\"{0}\"", sField);
                                break;
                            //「文字列フィールドだけ囲む」の場合
                            case enumFieldEnclosed.StringField:
                                sField = sField.Replace("\"", "\"\"");
                                sbContents.AppendFormat("\"{0}\"", sField);
                                break;
                            //「特殊文字列を含む文字列フィールドだけ囲む」の場合
                            case enumFieldEnclosed.ContainingSpecialCharactersField:
                                sField = sField.Replace("\"", "\"\"");
                                if (sField.IndexOf(opt.sFiledSeparator) != -1)
                                {
                                    sbContents.AppendFormat("\"{0}\"", sField);
                                }
                                else if (sField.IndexOf(opt.sLineBreak) != -1)
                                {
                                    sbContents.AppendFormat("\"{0}\"", sField);
                                }
                                else if (sField.IndexOf("\"") != -1)
                                {
                                    sbContents.AppendFormat("\"{0}\"", sField);
                                }
                                else
                                {
                                    sbContents.AppendFormat("{0}", sField);
                                }
                                break;
                        }
                        sbContents.Append(opt.sFiledSeparator);
                    }
                    // 真偽型(Boolean)の場合
                    else if (objField is Boolean)
                    {
                        string sValue;
                        // True/Falseで出力
                        if (opt.bBooleanTypeFormat)
                        {
                            sValue = ((bool)objField).ToString();
                        }
                        // 1/0で出力
                        else
                        {
                            sValue = ((bool)objField) ? "1" : "0";
                        }
                        sbContents.AppendFormat("{1}{0}{1}", sValue, sFieldEnclosed);
                        sbContents.Append(opt.sFiledSeparator);
                    }
                    // 日時(DateTime)
                    else if (objField is DateTime)
                    {
                        string sFormat = "{1}{0:" + opt.sDateTimeTypeFormat + "}{1}";
                        sbContents.AppendFormat(sFormat, objField, sFieldEnclosed);
                        sbContents.Append(opt.sFiledSeparator);
                    }
                    // 数値型(Decimal/Double/Int16/Int32/Int64/Single/UInt16/UInt32/UInt64)
                    // 日時(TimeSpan)
                    else
                    {
                        sbContents.AppendFormat("{1}{0}{1}", objField, sFieldEnclosed);
                        sbContents.Append(opt.sFiledSeparator);
                    }
                }
                // 最後のフィールド区切りを削除
                sbContents.Remove(sbContents.Length - opt.sFiledSeparator.Length, opt.sFiledSeparator.Length);
                // 行区切り挿入
                sbContents.Append(opt.sLineBreak);
            }
            // 最終レコードの行区切り文字を削除
            if (!opt.bLastRecordLineBreak && sbContents.Length > 0)
            {
                sbContents.Remove(sbContents.Length - opt.sLineBreak.Length, opt.sLineBreak.Length);
            }
            //-----------------------------------------------------------------------------------------
            // ファイル書込
            //-----------------------------------------------------------------------------------------
            using (StreamWriter sw = new StreamWriter(sDustFilePath, false, opt.enc))
            {
                sw.Write(sbContents.ToString());
                sw.Close();
            }
        }
    }
    
    


    
    using System;
    using System.Data;
    using System.Text;
    
    class Program
    {
        static void Main(string[] args)
        {
            //-------------------------------------------------------------------------------------
            // 表示用データ作成
            //-------------------------------------------------------------------------------------
            DataTable dtData = new DataTable();
            // 列作成
            dtData.Columns.Add("colInt32", typeof(Int32));
            dtData.Columns.Add("colInt64", typeof(Int64));
            dtData.Columns.Add("colDouble", typeof(Double));
            dtData.Columns.Add("colDecimal", typeof(Decimal));
            dtData.Columns.Add("colNull", typeof(Int32));
            dtData.Columns.Add("colDateTime", typeof(DateTime));
            dtData.Columns.Add("colBoolean", typeof(Boolean));
            dtData.Columns.Add("colString", typeof(String));
            dtData.Columns.Add("colSpecialString", typeof(String));
            // データ投入
            for (int i = 1; i <= 5; i++)
            {
                DataRow dr = dtData.NewRow();
                dr["colInt32"] = i;
                dr["colInt64"] = i * i;
                dr["colDouble"] = 1.1 * i;
                dr["colDecimal"] = 10.1 * i;
                dr["colNull"] = DBNull.Value;
                dr["colDateTime"] = new DateTime(2010, 1, i, 23, 59, 59);
                dr["colBoolean"] = (i % 2 == 0) ? true : false;
                dr["colString"] = string.Format("文字列{0}", (char)('A' + i - 1));
                if (i % 5 == 1)
                {
                    dr["colSpecialString"] = ",";
                }
                else if (i % 5 == 2)
                {
                    dr["colSpecialString"] = "\t";
                }
                else if (i % 5 == 3)
                {
                    dr["colSpecialString"] = "\r\n";
                }
                else if (i % 5 == 4)
                {
                    dr["colSpecialString"] = "\"";
                }
                else
                {
                    dr["colSpecialString"] = "";
                }
                dtData.Rows.Add(dr);
            }
            //-------------------------------------------------
            // CSV/TSVファイル作成
            //-------------------------------------------------
            DataTable2CharacterSeparatedValues.Option opt = new DataTable2CharacterSeparatedValues.Option();
            // 文字コード
            opt.enc = Encoding.GetEncoding("Shift-JIS");
            // フィールド区切り(","・"\t"のいずれか)
            opt.sFiledSeparator = ",";
            // 行区切り("\r\n"・"\r"・"\n"のいずれか)
            opt.sLineBreak = "\r\n";
            // フィールド囲み(ダブルクォーテーション(")の囲み方を指定)
            opt.enFieldEnclosed = DataTable2CharacterSeparatedValues.enumFieldEnclosed.AllField;
            // ヘッダ行を作成
            opt.bOutputHeader = true;
            // 最終レコードの後ろを改行
            opt.bLastRecordLineBreak = true;
            // Boolean型の出力形式(true:True/False or false:1/0)
            opt.bBooleanTypeFormat = false;
            // DateTime型の出力書式
            opt.sDateTimeTypeFormat = "yyyy/MM/dd hh:mm:ss";
            // ファイル作成
            string sTempFilePath = @"c:\temp\test.csv";
            DataTable2CharacterSeparatedValues.CreateFile(dtData, sTempFilePath, opt);
        }
    }
    
    

    上記ソースで作成されるCSVファイルの内容


  • RFC 4180
  • Comma-Separated Values - Wikipe
  • DataColumn.DataType プロパティ

  • ASP.NET(C#)でJQuery+TableSorterを利用

    ASP.NET(C#)とJQuery+TableSorterを連携してみた。
    対象はグリッド系コントロールのGridView・ListView・Repeater・DataList・DataGrid。



    ■開発・運用環境
    • Visual Studio 2008 SP1
    • .NET Framework 3.5 SP1
    • ASP.NET3.5

    ■ブラウザ
    • IE6,IE8
    • Firefox3
    • Opera9
    • Chrome2.0


    TableSorterではtableタグ内にtheadタグが必須である。
    しかしASP.NETのグリッド系コントロールは「デフォルト設定ではtheadを出力しない」もしくは「theadを出力できない」。(下表参照)
    コントロール 出力可否(*1) 設定方法
    GridView プロパティで設定。
    ListView Templateコントロールにtableタグを記述。
    Repeater Templateコントロールにtableタグを記述。
    DataList × 「サーバサイド設定」「JavaScript(*2)」連携が必要。
    DataGrid × 「サーバサイド設定」「JavaScript(*2)」連携が必要。
    (*1)出力可否の基準は「簡単に出力できるか?」である。サーバサイドでもtheadタグの出力方法はあると思う。(方法は不明)。
    (*2)JavaScript処理内でtableタグのinnerHTMLとouterHTMLに対して読み書きしているが、innerHTMLとouterHTMLにはブラウザ依存がある。

    ASP.NETでTableSorterを利用する為には、この制限を突破しtheadタグを出力させる必要がある。

    なお後述のサンプルソースではtheadのほかにtbodyも出力している。
    本ページでは関係ないことだが他のテーブル操作プラグインでtbodyが必要な場合もあるため一応出力している。


    ■GridView
    ①Page_Load等で以下のプロパティ設定を行う。
    
    GridView1.UseAccessibleHeader = true;
    GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;
    
    
    ②JavaScriptでtablesorter()関数呼び出し。
    
    $(function () {
        $("#GridView1").tablesorter();
    };
    
    

    ■ListView
    ①aspxファイルでLayoutTemplate・ItemTemplateにtableタグを記述。
    
    <asp:ListView ID="ListView1" runat="server">
        <LayoutTemplate>
            <table id="ListView1Table" class="tablesorter">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>文字列</th>
                    </tr>
                </thead>
                <tbody>
                    <asp:PlaceHolder runat="server" ID="itemPlaceholder" />
                </tbody>
            </table>
        </LayoutTemplate>
        <ItemTemplate>
                <tr>
                    <td><%# Eval("No") %></td>
                    <td><%# Eval("文字列") %></td>
                </tr>
        </ItemTemplate>
    </asp:ListView>
    
    
    ②JavaScriptでtablesorter()関数呼び出し。
    
    $(function () {
        $("#ListView1Table").tablesorter();
    };
    
    

    ■Repeater
    ①aspxファイルでHeaderTemplate・ItemTemplate・FooterTemplateにtableタグを記述。
    
    <asp:Repeater ID="Repeater1" runat="server">
         <HeaderTemplate>
            <table id="Repeater1Table" class="tablesorter">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>文字列</th>
                    </tr>
                </thead>
                <tbody>
        </HeaderTemplate>
        <ItemTemplate>
                    <tr>
                        <td><%# Eval("No") %></td>
                        <td><%# Eval("文字列")%></td>
                    </tr>
        </ItemTemplate>
        <FooterTemplate>
                </tbody>
            </table>
        </FooterTemplate>
    </asp:Repeater>
    
    
    ②JavaScriptでtablesorter()関数呼び出し。
    
    $(function () {
        $("#Repeater1Table").tablesorter();
    };
    
    

    ■DataList
    ①aspxファイルでHeaderTemplate・ItemTemplate・FooterTemplateにtableタグを記述。
    
    <asp:DataList ID="DataList1" runat="server">
        <HeaderTemplate>
            <table id="DataList1Table" class="tablesorter">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>文字列</th>
                    </tr>
                </thead>
                <tbody>
        </HeaderTemplate>
        <ItemTemplate>
                    <tr>
                        <td><%# Eval("No") %></td>
                        <td><%# Eval("文字列")%></td>
                    </tr>
        </ItemTemplate>
        <FooterTemplate>
                </tbody>
            </table>
        </FooterTemplate>
    </asp:DataList>
    
    
    ②Page_Load等で以下のプロパティ設定を行う。
    
    DataList1.RepeatLayout = RepeatLayout.Flow;
    
    
    ③JavaScriptで②の設定変更で出力されるspan・brタグを除去後、tablesorter()関数呼び出し。
    
    $(function () {
        var objDataList1Table = document.getElementById("DataList1Table")
        if ($.browser.msie)
        {
            // IE
            var sDataList1TableHTML = objDataList1Table.outerHTML;
            sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
            sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
            sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
            objDataList1Table.outerHTML = sDataList1TableHTML;
        }
        else
        {
            // FireFox,Opera,Chrome
            var sDataList1TableHTML = objDataList1Table.innerHTML;
            sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
            sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
            sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
            objDataList1Table.innerHTML = sDataList1TableHTML;
        }
        $("#DataList1Table").tablesorter();
    });
    
    

    ■DataGrid
    ①Page_Load等で以下のプロパティ設定を行う。
    
    DataGrid1.ShowHeader = false;
    
    
    ②JavaScriptで「theadタグの付与」「ヘッダー列作成」「tableからstyle属性削除」後、tablesorter()関数呼び出し。
    
    $(function () {
        var objDataGrid1 = document.getElementById("DataGrid1")
        if ($.browser.msie)
        {
            // IE
            var sNewOuterHTML;
            var sNewInnerHTML = "";
            sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
            sNewInnerHTML += objDataGrid1.innerHTML;
            sNewOuterHTML = objDataGrid1.outerHTML.replace(objDataGrid1.innerHTML, sNewInnerHTML);
            objDataGrid1.outerHTML = sNewOuterHTML;
        }
        else
        {
            // FireFox,Opera,Chrome
            var sNewInnerHTML = "";
            sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
            sNewInnerHTML += objDataGrid1.innerHTML;
            objDataGrid1.innerHTML = sNewInnerHTML;
        }
        $("#DataGrid1").removeAttr("style");
        $("#DataGrid1").tablesorter();
    });
    
    

    ASP.NET(C#)とJQuery+TableSorterを連携したときのサンプルソースを記述する。
    
    <%@ Page Language="C#" AutoEventWireup="true" %>
    <%@ Import Namespace="System.Data" %>
    <!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>各種グリッド+TableSorter</title>
        <script src="../js/jquery/jquery-1.3.2.js" type="text/ecmascript"></script>
        <link href="../js/Tablesorter/blue/style.css" rel="stylesheet" type="text/css" />
        <script src="../js/Tablesorter/jquery.tablesorter.js" type="text/javascript"></script>
        <script type="text/C#" runat="server">
        /// <summary>
        /// Page_Load
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                //-------------------------------------------------------------------------------------
                // DataTable作成
                //-------------------------------------------------------------------------------------
                DataTable dt = new DataTable("DataTable");
                dt.Columns.Add("No", typeof(int));
                dt.Columns.Add("文字列", typeof(string));
                for (int i = 1; i <= 3; i++)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = i;
                    dr[1] = string.Format("文字{0}", 4-i);
                    dt.Rows.Add(dr);
                }
                //-------------------------------------------------------------------------------------
                // テーブル系コントロール設定
                //-------------------------------------------------------------------------------------
                // GridView
                GridView1.DataSource = dt;
                GridView1.DataBind();
                GridView1.UseAccessibleHeader = true;
                GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;
                // ListView
                ListView1.DataSource = dt;
                ListView1.DataBind();
                // Repeater
                Repeater1.DataSource = dt;
                Repeater1.DataBind();
                // DataList
                DataList1.DataSource = dt;
                DataList1.DataBind();
                DataList1.RepeatLayout = RepeatLayout.Flow;
                // DataGrid
                DataGrid1.DataSource = dt;
                DataGrid1.DataBind();
                DataGrid1.ShowHeader = false;
            }
        }
        </script>
        <script type="text/ecmascript">
            $(function () {
                //-------------------------------------------------------------------------------------
                // Tablesorterの有効化
                // <注意1>
                // Tablesorterにはthead,tbodyが必要。しかしDataList,DataGridコントロールは
                // サーバサイド処理でthead,tbodyを出すのが困難なため、クライアントスクリプトで
                // 強引にthead,tbodyを付与している。
                // <注意2>
                // 注意1に関連することだがIE系はtableタグのinnerHTMLは読取専用である。
                // このためinnerHTMLの代用としてouterHTMLを使っている。
                // ちなみにFirefoxはouterHTMLがない。
                // <注意3>
                // DataListはHTML上部にspanタグをレンダリングする。これがレイアウトをおかしくする。
                //-------------------------------------------------------------------------------------
                // GridView
                $("#GridView1").tablesorter();
                // ListView
                $("#ListView1Table").tablesorter();
                // Repeater
                $("#Repeater1Table").tablesorter();
                // DataList
                var objDataList1Table = document.getElementById("DataList1Table")
                if ($.browser.msie)
                {
                    // IE
                    var sDataList1TableHTML = objDataList1Table.outerHTML;
                    sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
                    sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
                    sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
                    objDataList1Table.outerHTML = sDataList1TableHTML;
                }
                else
                {
                    // FireFox,Opera,Chrome
                    var sDataList1TableHTML = objDataList1Table.innerHTML;
                    sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
                    sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
                    sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
                    objDataList1Table.innerHTML = sDataList1TableHTML;
                }
                $("#DataList1Table").tablesorter();
                // DataGrid
                var objDataGrid1 = document.getElementById("DataGrid1")
                if ($.browser.msie)
                {
                    // IE
                    var sNewOuterHTML;
                    var sNewInnerHTML = "";
                    sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
                    sNewInnerHTML += objDataGrid1.innerHTML;
                    sNewOuterHTML = objDataGrid1.outerHTML.replace(objDataGrid1.innerHTML, sNewInnerHTML);
                    objDataGrid1.outerHTML = sNewOuterHTML;
                }
                else
                {
                    // FireFox,Opera,Chrome
                    var sNewInnerHTML = "";
                    sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
                    sNewInnerHTML += objDataGrid1.innerHTML;
                    objDataGrid1.innerHTML = sNewInnerHTML;
                }
                $("#DataGrid1").removeAttr("style");
                $("#DataGrid1").tablesorter();
            });
        </script>
    </head>
    <body>
    <form id="form1" runat="server">
    GridView:
    <asp:GridView ID="GridView1" runat="server" CssClass="tablesorter"></asp:GridView>
    ListView:<br />
    <asp:ListView ID="ListView1" runat="server">
        <LayoutTemplate>
            <table id="ListView1Table" class="tablesorter">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>文字列</th>
                    </tr>
                </thead>
                <tbody>
                    <asp:PlaceHolder runat="server" ID="itemPlaceholder" />
                </tbody>
            </table>
        </LayoutTemplate>
        <ItemTemplate>
                <tr>
                    <td><%# Eval("No") %></td>
                    <td><%# Eval("文字列") %></td>
                </tr>
        </ItemTemplate>
    </asp:ListView>
    Repeater:<br />
    <asp:Repeater ID="Repeater1" runat="server">
         <HeaderTemplate>
            <table id="Repeater1Table" class="tablesorter">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>文字列</th>
                    </tr>
                </thead>
                <tbody>
        </HeaderTemplate>
        <ItemTemplate>
                    <tr>
                        <td><%# Eval("No") %></td>
                        <td><%# Eval("文字列")%></td>
                    </tr>
        </ItemTemplate>
        <FooterTemplate>
                </tbody>
            </table>
        </FooterTemplate>
    </asp:Repeater>
    DataList:<br />
    <asp:DataList ID="DataList1" runat="server">
        <HeaderTemplate>
            <table id="DataList1Table" class="tablesorter">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>文字列</th>
                    </tr>
                </thead>
                <tbody>
        </HeaderTemplate>
        <ItemTemplate>
                    <tr>
                        <td><%# Eval("No") %></td>
                        <td><%# Eval("文字列")%></td>
                    </tr>
        </ItemTemplate>
        <FooterTemplate>
                </tbody>
            </table>
        </FooterTemplate>
    </asp:DataList>
    DataGrid:<br />
    <asp:DataGrid ID="DataGrid1" runat="server" CssClass="tablesorter" AutoGenerateColumns="false">
        <Columns>
            <asp:BoundColumn DataField="No" />
            <asp:BoundColumn DataField="文字列" />
        </Columns>
    </asp:DataGrid>
    </form>
    </body>
    </html>
    
    



    上記ソースからASP.NETのグリッド系コントロールとTableSorterの有効な組み合わせなのは、GridView・ListView・Repeater だと考えられる。
    DataList・DataGridも利用可能だがJavaScriptによるタグ操作がある為、表示後にサーバサイド処理と連携すると 何らかの問題が発生する可能性が高い。
    またDataListはspan・brタグの置換が発生するため画面自由度が低減する。
    他にDataListはFirefox・Chromeでコントロール上部のレイアウトが崩れることも確認している。




    サービスアプリ追加(データテキストファイルビューア)

    Oncemail Labテキストのデータテキストファイルビューアサービスを追加。

    このサービスではデータテキストファイル(CSV・TSV・XML)をグリッドに表示します。


    ■サービス公開先
    Oncemail Lab


    ■2009/06/09時点での公開サービス

    サービス名 概要
    OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
    Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
    PDFのファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
    PDFのファイル分割サービス PDFファイルを2つのファイルに分割します。
    PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
    デュアルマップサービス 「Yahoo!地図」「Googleマップ」の異なるタイプの地図を2つ同時に表示・操作できます。
    ランダムパスワード生成サービス ランダムなパスワードを生成します。
    CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
    画像ファイル一括変換サービス 複数の画像ファイルを一括で画像形式・サイズ・透過等の変換を行います。
    ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
    ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
    ファイルの7z圧縮サービス ファイルを7z圧縮します。
    テキストの正規表現置換サービス テキストを正規表現で置換します。
    データテキストファイルビューアサービス データテキストファイル(CSV・TSV・XML)をグリッド表示します。

    « 2009年5月 | トップページ | 2009年7月 »

    Google AdSense


    • ---

    Amazon ウィジェット

    • ウィジェット

    @niyo_naのツイート

    無料ブログはココログ

    Google Analytics