ASP.NET MVC で、データベースに保存されているファイルをユーザーに送り返す際に問題が発生しています。必要なのは、ファイルを表示し、ブラウザーに送信された MIME タイプによって処理方法を決定できるようにするためのリンクと、ダウンロードを強制するためのリンクの 2 つのリンクをリストするビューです。
というファイルを表示することを選択しSomeRandomFile.bak
、ブラウザにこの種類のファイルを開くための関連プログラムがない場合、デフォルトでダウンロード動作を実行しても問題ありません。ただし、 というファイルを表示することを選択した場合、SomeRandomFile.pdf
またはSomeRandomFile.jpg
ファイルを単に開くようにしたい場合、ファイルの種類に関係なくダウンロード プロンプトを強制できるように、ダウンロード リンクを横に残しておきたいと思います。これは理にかなっていますか?
試してみたところFileStreamResult
、ほとんどのファイルで機能しました。コンストラクタはデフォルトでファイル名を受け入れないため、不明なファイルには URL に基づいてファイル名が割り当てられます (コンテンツ タイプに基づいて付与する拡張子はわかりません)。ファイル名を指定して強制すると、ブラウザでファイルを直接開くことができなくなり、ダウンロード プロンプトが表示されます。他にこれに遭遇した人はいますか?
これらは私がこれまで試したことの例です。
//Gives me a download prompt.
return File(document.Data, document.ContentType, document.Name);
//Opens if it is a known extension type, downloads otherwise (download has bogus name and missing extension)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType);
//Gives me a download prompt (lose the ability to open by default if known type)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType) {FileDownloadName = document.Name};
助言がありますか?
更新:この質問は多くの人の共感を呼んでいるようなので、更新情報を投稿しようと思いました。Oskar が追加した、下記の承認済み回答の国際文字に関する警告は完全に正当なもので、クラスを使用しているために何度か遭遇しましたContentDisposition
。それ以来、実装を更新してこの問題を修正しました。以下のコードは、ASP.NET Core (Full Framework) アプリでこの問題を最近再現したものですが、クラスを使用しているため、古い MVC アプリケーションでも最小限の変更で動作するはずですSystem.Net.Http.Headers.ContentDispositionHeaderValue
。
using System.Net.Http.Headers;
public IActionResult Download()
{
Document document = ... //Obtain document from database context
//"attachment" means always prompt the user to download
//"inline" means let the browser try and handle it
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = document.FileName
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
return File(document.Data, document.ContentType);
}
// an entity class for the document in my database
public class Document
{
public string FileName { get; set; }
public string ContentType { get; set; }
public byte[] Data { get; set; }
//Other properties left out for brevity
}
ベストアンサー1
public ActionResult Download()
{
var document = ...
var cd = new System.Net.Mime.ContentDisposition
{
// for example foo.bak
FileName = document.FileName,
// always prompt the user for downloading, set to true if you want
// the browser to try to show the file inline
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(document.Data, document.ContentType);
}
注意:File()
上記のサンプル コードでは、ファイル名の国際文字が適切に考慮されていません。関連する標準化については、RFC6266 を参照してください。最近のバージョンの ASP.Net MVC のメソッドとクラスでは、これが適切に考慮されていると思いますContentDispositionHeaderValue
。 - Oskar 2016-02-25