データベースに格納されているファイルをASP.NET MVCのユーザーに送り返すときに問題が発生しました。私が欲しいのは、2つのリンクをリストするビューです。1つはファイルを表示し、ブラウザに送信されたMIMEタイプに処理方法を決定させ、もう1つはダウンロードを強制します。
呼び出されたファイルを表示することを選択し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(フルフレームワーク)アプリでのこの問題の最新の具体化によるものですが、System.Net.Http.Headers.ContentDispositionHeaderValue
クラスを使用しているため、古いMVCアプリケーションでも最小限の変更で機能するはずです。
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
}