ASP.NET MVC ファイルのダウンロード
ASP.NET MVCでファイルをダウンロードする方法メモ
Controller サーバーのフォルダにファイルが存在する場合
public ActionResult Download() { var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; return File(Server.MapPath("~/App_Data/dummy.xlsx"), contentType, "download.xlsx"); }
FileStreamからダウンロード
public ActionResult Download() { MemoryStream memoryStream = new MemoryStream(); using (FileStream fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.Read)) { fileStream.CopyTo(memoryStream); } var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; return File(memoryStream.ToArray(), contentType, "download.xlsx"); }
IE11の互換モード使用で、表示がおかしくなる
IE11とEdgeでの表示が違う
今時ながらの事だが、IE11を使っている現場で、しかも互換モードが適用されているみたく、作ったページがおかしくなるらしい。
対策
HTMLのmetaタグに以下の内容を追加した
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
とりあえず、直ったみたいなので、メモっとく
ASP.NET MVCをIISの仮想フォルダに公開したら404エラーになる件
エラーの原因
ASP.NETのルーティングとJavascriptのURL実行部をIISの仮想フォルダまでは考慮していなかったため、ルーティングが失敗し、存在しないページを探しに行ってエラーになる感じ
エラーになる主な部分
- HTML部のformactionとスクリプトソース設定の方が失敗していました。
<form method="post" enctype="multipart/form-data"> <button itype="submit" formaction="/Home/Action1" >処理</button> </form> <script src="~/Scripts/IMyScript.js"></script>
- javascriptは言うこともないが、パス合わなくなりますね。
var ret = $.ajax({ type: 'GET', url: '/Home/Action1', async: false }).responseText;
対応した部分
- RouteConfigに仮想フォルダ用のルーティングを追加
routes.MapRoute( name:="SUB", url:="SUB/{controller}/{action}/{code}", defaults:=new {controller = "Home", action = "Index", code = UrlParameter.Optional} )
- View部分には@Url.Contentを使用
<form method="post" enctype="multipart/form-data"> <button itype="submit" formaction='@Url.Content("~/Home/Action1")' >処理</button> </form> <script src='@Url.Content("~/Scripts/IMyScript.js")'></script>
*JavascriptにはルートのUrlを再生性するため、_Layoutにルート情報を隠しといて再生成関数を配置
<input id="hdnRootUrl" type="hidden" value='@Url.Content("~/")' />
var myurl = $('#hdnRootUrl').val() + '/Home/Action1'; myurl.replace('//', '/'); var ret = $.ajax({ type: 'GET', url: myurl, async: false }).responseText;
ASP.NET ファイルアップロード関連トラブル
ファイルアップロード時、以下のエラーに遭遇
- maxAllowedContentLength エラー
- 要求の長さの最大値を超えました。 POSTされるファイルの最大サイズが引っかかる場合、発生。 maxRequestLengthが足りない場合起きるエラー 大容量のCSVファイルなどは最大容量で引っかかるらしい、 以下の様に、httpRuntimeに最大設定で回避
<system.web> <httpRuntime maxRequestLength="65535"/> </system.web>
IIS7以降ではサーバの要求フィルター設定項目でも、ファイルサイズの 上限を設定する必要がある。らしい
<system.webServer> <modules runAllManagedModulesForAllRequests="true" /> <security> <requestFiltering> <requestLimits maxAllowedContentLength="120000000"/> </requestFiltering> </security> </system.webServer>
CsvHelperを利用して、Csvデータを取り込む
Nugetより、CsvHelperをインストールする。
Csvを読み取り、モデルに設定してくれるパッケージ まあ、便利そうだから入れる。
Csvファイルサンプル
Code,Name 001,Tokyo 002,Osaka 003,Nagoya 004,Hakata 005,Yokohama
Csv取込用モデル作成
Public class MyData { Public string Code {get; set;} Public string Name {get; set;} }
Csvファイルを読み取る
Public void main() { Dim fs As FileStream = System.IO.File.Open("csv_data\\testcsv.csv", FileMode.Open) using(var sr = new StreamReader(fileStream, System.Text.Encoding.GetEncoding("shift_jis")) { var cr = new CsvHelper.CsvReader(sr); While(csvReader.Read()){ var data = csvReader.GetRecord(Of MyData)() } } }
注意点
CsvHelperでモデルにバインドする場合は、ヘッダーにモデルの項目名と一致しないとエラーになるため、注意が必要
SQLCMDでSELECT結果をCSV出力する。
SELECT文の結果をSQLCMDを利用し、CSV出力する
query.sql
クエリを指定したファイル
SET NOCOUNT ON; SELECT [Code] ,[Name] FROM [dbo].[Data] ;
SET NOCOUNT ON;を削除すると件数が一緒に出力される。
SQLCMD
query.sqlを読み取り、output.csvファイルへ出力する。
SQLCMD -S localhost -U sa -P {password} -d {dbname} -i query.sql -s, -W -h -1 -o output.csv
- オプションについて
命令 | 説明 |
---|---|
-S | サーバ名 |
-U | ログイン |
-P | パスワード |
-d | データベース |
-i | スクリプトファイル |
-s | 区切り文字 |
-W | 余計な空白を省く |
-h | -1でヘッダ非表示 |
-o | 出力ファイル |
-v | 変数 (param='001' => $(param)) |
-h オプションについて
-h -1の場合、ヘッダーが一切出力されなくなる。
001,Tokyo 002,Osaka 003,Nagoya 004,Hakata 005,Yokohama
-hオプションなしの場合
Code,Name ----,---- 001,Tokyo 002,Osaka 003,Nagoya 004,Hakata 005,Yokohama
ASP.NET MVC FILE UPLOAD
ASP.NET MVCでファイルをアップロードする方法を調べる
以外なところでハマり、悩まされたので、メモる。
Controllerでもファイルの受け取り方法
- Modelにバインドして取得する。
- Request.Filesから、inputのnameをキーに取得する。
public ActionResult Upload(FormCollection form) { var file = Request.Files["uploadfile"]; } もしくは public ActionResult Upload(MyViewModel model) { model.UploadFile; // -> すでにバインド状態となる。 }
View側での準備
- formのmethodはPOST
- formのenctypeは"multipart/form-data" ←これがわからず悩んだ
- inputのtype=file, name=取得キーもしくはModelの項目名と一致すること
<form method="post" enctype="multipart/form-data"> <input type="file" name="uploadfile" /> <button type="submit" > UPLOAD</button> </form> もしくは @Using(Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype="multipart/form-data"}) { <input type="file" name="uploadfile" /> <button type="submit" > UPLOAD</button> }
ViewModel定義
基本、対象項目の型を”HttpPostedFileBase”にしておくだけ
Public calss MyViewModel
{
public HttpPostedFileBase UploadFile;
}