.NET TIPS

[ASP.NET]データベースの内容をクライアントにダウンロード提供するには?

山田 祥寛
2004/10/01

 データベース内のデータをクライアントにCSV(Comma Separated Value:カンマ区切りテキスト)やTSV(Tab Separated Value:タブ区切りテキスト)などの形式で提供したいという状況は意外と多い。

 というのも、DataGridコントロールなどで出力された一覧データは、なるほど一覧性に富んで見栄えがするものの、ローカル環境でデータを再利用するような用途には不向きなためだ。Webアプリケーション上で提供された情報を、Microsoft ExcelやAccessなどにインポートしたいという場合には、(DataGridコントロールの出力一覧データよりも)CSV形式やTSV形式のデータの方が適している。

 そこで本稿では、Repeaterコントロールを利用して、データベース・サーバ内のデータをCSV形式に加工し、それをクライアントに対してダウンロード提供するためのサンプル・プログラムを紹介する。

 なお、本サンプル・プログラムを利用する場合には、あらかじめデータベース・サーバ上に以下のようなbooksテーブルを作成しておく必要がある。

フィールド名 データ型 概要
isbn VARCHAR(20) ISBNコード(主キー)
title VARCHAR(100) 書名
price INT 価格
publish VARTCHAR(30) 出版社名
published DATETIME 発刊日
booksテーブルのフィールド・レイアウト

 それでは、具体的なコードを眺めてみよう。

<%@ Page ContentType="application/octet-stream"
  Language="C#" ResponseEncoding="Shift_JIS" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script runat="Server">

SqlDataReader objDr;

void Page_Load(Object sender, EventArgs e) {

  // ダウンロード用ファイルのデフォルトの名前を指定
  Response.AppendHeader("Content-Disposition","attachment; filename=down.csv");

  // booksテーブルからデータを取り出し、
  // Repeaterコントロールにバインド

  SqlConnection db=new SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet");
  SqlCommand objCom=new SqlCommand("SELECT isbn,title,price,publish,published FROM books ORDER BY published DESC",db);
  db.Open();
  objDr=objCom.ExecuteReader();
  DataBind();
  db.Close();
}
</script>

<asp:Repeater id="objRep" runat="Server" DataSource="<%#objDr %>">
  <HeaderTemplate>ISBN,書名,価格,出版社,発刊日
  </HeaderTemplate>
  <ItemTemplate><%# DataBinder.Eval(Container.DataItem, "isbn") %>,<%# DataBinder.Eval(Container.DataItem, "title") %>,<%# DataBinder.Eval(Container.DataItem, "price") %>,<%# DataBinder.Eval(Container.DataItem, "publish") %>,<%# DataBinder.Eval(Container.DataItem, "published") %>
  </ItemTemplate>
</asp:Repeater>
CSV形式に加工したデータをクライアントにダウンロード提供するサンプル・プログラム(C#:dl_cs.aspx)
 
<%@ Page ContentType="application/octet-stream"
  Language="VB" ResponseEncoding="Shift_JIS" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script runat="Server">

Dim objDr As SqlDataReader

Sub Page_Load(sender As Object, e As EventArgs)

  ' ダウンロード用ファイルのデフォルトの名前を指定
  Response.AppendHeader("Content-Disposition","attachment; filename=down.csv")

  ' booksテーブルからデータを取り出し、
  ' Repeaterコントロールにバインド

  Dim db As New SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet")
  Dim objCom As New SqlCommand("SELECT isbn,title,price,publish,published FROM books ORDER BY published DESC",db)
  db.Open()
  objDr=objCom.ExecuteReader()
  DataBind()
  db.Close()
End Sub
</script>

<asp:Repeater id="objRep" runat="Server" DataSource="<%#objDr %>">
  <HeaderTemplate>ISBN,書名,価格,出版社,発刊日
  </HeaderTemplate>
  <ItemTemplate><%# DataBinder.Eval(Container.DataItem, "isbn") %>,<%# DataBinder.Eval(Container.DataItem, "title") %>,<%# DataBinder.Eval(Container.DataItem, "price") %>,<%# DataBinder.Eval(Container.DataItem, "publish") %>,<%# DataBinder.Eval(Container.DataItem, "published") %>
  </ItemTemplate>
</asp:Repeater>
CSV形式に加工したデータをクライアントにダウンロード提供するサンプル・プログラム(VB.NET:dl_vb.aspx)

 上記のコードで、注目すべきポイントは以下の3点だ。

(1)ダウンロード・データであることを宣言する

 読者諸兄もご存じのように、HTTPプロトコルはネットワーク上を流れるデータ形式を何ら制限しない。サーバから送信された任意のデータ形式をどのように処理するかを決めるのは、クライアント側(ブラウザ)の役割だ。つまり、クライアントがデータ形式を判別できるように、サーバ側(ASP.NET)では処理を判別するためのキーとなる情報を送信する必要がある。そのキーが、Content-TypeヘッダとContent-Dispositionヘッダ(いずれもHTTPヘッダ)である。

 Content-Typeヘッダは送信されるコンテンツの型を指定するためのもので、上記サンプル・プログラムで使用している“application/octet-stream”はコンテンツが「任意のバイナリ・データ」であることを示している。一般的なブラウザは、“application/octet-stream”形式のコンテンツを受け取った場合、ダウンロード・データとして処理を行う。

 もう1つのContent-Dispositionヘッダは、コンテンツの処理方法を指定するためのヘッダ情報だ。Content-Dispositionヘッダについては、Content-Typeヘッダのように値を指定するための専用のメソッドや属性は用意されていないので、HttpResponse.AppendHeaderメソッドを利用する必要がある。ここでは、filenameパラメータを指定することで、ダウンロード時にデフォルトで表示されるべきファイル名を指定している。ただし、ここで指定されるファイル名はあくまで「デフォルト」で表示されるファイル名というだけであって、クライアントが必ず指定された名前でファイルを保存することを保証するものではないので、注意すること。

(2)応答エンコーディングを“Shift_JIS”に指定

 デフォルトでASP.NETの応答エンコーディングは“UTF-8”である。しかし一般的に、ダウンロードしたデータはExcelやAccessなどのアプリケーション上で利用することが想定される。そして、これらアプリケーションのデフォルト・エンコーディングが“Shift_JIS”であることを考えれば、ダウンロード・データもこれに合わせておくのが望ましいだろう。もしもデフォルトのUTF-8のままでデータを提供した場合には、ダウンロード後にユーザーはデータの文字コード変換などを行わなければならなくなってしまう。

 レスポンスの文字エンコーディングは、@PageディレクティブのResponseEncoding属性で指定することができる。

(3)テンプレート内には不要な改行/空白は含めない

 Repeaterコントロールは、指定されたテンプレートに従って、繰り返しデータを出力するためのコントロールだ。DataListコントロールやDataGridコントロールのように、複雑な機能は用意されていないが、DataListやDataGridでは表現しにくい変則的なレイアウトを出力したい場合に利用することができる(詳細については、「プログラミングASP.NET 第12回」を参照していただきたい)。

 さて、このRepeaterコントロールであるが、HTMLを記述するのと同じ感覚でテンプレートを記述していると、思わぬ落とし穴に陥ることがある。HTMLはご存じのとおり、改行や空白を基本的に認識しない言語であるが、片やCSV/TSVでは改行や空白はデータ(レコード)の区切りを表す重要な情報だ。つまり、テンプレート内(ItemTemplate要素内)に不要な改行や空白を含めてしまうと、正しい形式のデータが生成されないことになってしまう。注意してほしい。

 以上が理解できたら、さっそく、サンプル・プログラムを起動してみよう。以下のようなダウンロード・ダイアログが開けば、成功だ。

サンプル・プログラムを起動すると表示されるダウンロード・ダイアログ

 ダウンロードしたファイルは、Excelなどのアプリケーションで確認することができる。

ダウンロード・データをMicrosoft Excelで開いた画面

 この画面は、ダウンロードしたデータ・ファイルを、実際にExcelに読み込んで表示したものだ。End of Article

カテゴリ:Webフォーム 処理対象:HTTPヘッダ
使用キーワード:@Pageディレクティブ
 
この記事と関連性の高い別の.NET TIPS
サーバにより指定されたファイル名でファイルをダウンロードして保存するには?
クリップボードからデータを受け取るには?
[ASP.NET]ListViewコントロールで非定型のリストを表示するには?
[ASP.NET]DataGridコントロールで大量のデータをページ表示するには?
[ASP.NET]Repeater/DataListコントロールのテンプレートを別ファイルで管理するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間