tekitoumemo’s diary

思ったことを書くだけ。長文版Twitter

ASP.NET Core MVCにおけるファイルダウンロードのあれこれ

f:id:tekitoumemo:20180709200515p:plain
結構サボってたー。ブログ書き続けるのは難しい!平日は寝たいし、休日は遊びたいし。

今回はASP.NET Core MVCでのファイルダウンロードの実装方法を説明します。ファイルダウンロードにもいろいろあって

  • ファイルを保存させる
  • ファイルをブラウザで表示させる

主にこの2つのパターンがあると思います。結構いろんなやり方があったのでその一部を書きます。

PhysicalFileResult

docs.microsoft.com
物理ファイルにアクセスしてファイルを操作する方法です。挙動はブラウザにファイルが表示されます。.net coreに移行する際など今までのディレクトリ構成を変えずに実装出来る方法です。

Startup.cs
物理的にアクセスする為にアクセスを許可します。今回は直下のImagesディレクトリを許可します。

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
    Path.Combine(Directory.GetCurrentDirectory(), "Images")),
    RequestPath = "/Images"
});


Controller
物理パスを取得し、PhysicalFileResultにパスとMIMEタイプを指定します。

public IActionResult PhysicalFileResult()
{
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "Images", "neet.png");
    return new PhysicalFileResult(filePath, MediaTypeNames.Image.Jpeg);
}

VirtualFileResult

docs.microsoft.com
これはURLで指定するような仮想パスを指定してファイルを取得する方法です。挙動はブラウザにファイルが表示されます。Controllerで完結するので比較的使いやすい部類かなと思います。
Controller
URLのパスとMIMEタイプを指定します。

public IActionResult VirtualFileResult()
{
    return new VirtualFileResult(@"/Images/wwwroot_neet.png", MediaTypeNames.Image.Jpeg);
}

FileContentResult

docs.microsoft.com
FileContentResultは二つ方法があります。こちらはDBに画像が格納されているパターンやバイナリを使う際に有効です。
まずはファイルがダウンロードされるパターン。

Controller
バイナリとMineタイプとファイル名を指定します。

public IActionResult FileContentResult()
{
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "Images", "neet.png");
    var file = System.IO.File.ReadAllBytes(filePath);
    return File(file, MediaTypeNames.Image.Jpeg, "neet.png");
}

ブラウザに表示するパターン
上記のコードでファイル名を省いたパターンです。

public IActionResult FileContentResult()
{
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "Images", "neet.png");
    var file = System.IO.File.ReadAllBytes(filePath);
    return File(file, MediaTypeNames.Image.Jpeg);
}

ResponceヘッダーのContent-Dispositionによってブラウザの挙動が変わるようで、ファイルを指定すると「attachment」になりファイルをダウンロードする動き、指定しないと「inline」になりファイルをブラウザで表示するような動きになります。

Responceヘッダを直接書きければ、同じように動くんですがわざわざやる意味もないのでここら辺を活用できればいいと思います。今回説明したパターンのコードを以下に置いとくので参考なれば。
github.com

【参考】
stackoverflow.com