私はAsp.Net MVCアプリケーションからユーザーがファイルをダウンロードできるようにFileResultを使うべきだと私に提案しました。しかし、私が見つけることができるこの唯一の例は常に画像ファイルに関係しています(content type image/jpegを指定する)。
しかし、ファイルの種類がわからない場合はどうすればよいですか。私のサイトのファイルエリアからほとんどすべてのファイルをユーザがダウンロードできるようにしたい。
これを行う1つの方法(コードについては の前の投稿 を参照してください)を読みました。 [名前を付けて保存]ダイアログに表示されるファイルは、ファイルパスからアンダースコア(folder_folder_file.ext)で連結されます。また、BinaryContentResultが見つかったカスタムクラスを使用するのではなく、FileResultを返すべきだと考える人もいます。
MVCでそのようなダウンロードを行うための「正しい」方法を知っている人はいますか?
編集:私は答え(下記)を得たが、他の誰かが興味を持っているならば私は完全な作業コードを投稿するべきだとちょうど思った:
public ActionResult Download(string filePath, string fileName)
{
string fullName = Path.Combine(GetBaseDir(), filePath, fileName);
byte[] fileBytes = GetFile(fullName);
return File(
fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
byte[] GetFile(string s)
{
System.IO.FileStream fs = System.IO.File.OpenRead(s);
byte[] data = new byte[fs.Length];
int br = fs.Read(data, 0, data.Length);
if (br != fs.Length)
throw new System.IO.IOException(s);
return data;
}
一般的なオクテットストリームのMIMEタイプを指定するだけです。
public FileResult Download()
{
byte[] fileBytes = System.IO.File.ReadAllBytes(@"c:\folder\myfile.ext");
string fileName = "myfile.ext";
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
MVCフレームワークはこれをネイティブにサポートします。 System.Web.MVC.Controller.File コントローラーは、 名前でファイルを返すためのメソッドを提供します / ストリーム / 配列 。
たとえば、ファイルへの仮想パスを使用すると、次のことができます。
return File(virtualFilePath, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(virtualFilePath));
.NET Framework 4.5を使用している場合は、 MimeMapping.GetMimeMapping (String FileName)を使用してファイルのMIMEタイプを取得します。これが私の行動の中で私が使った方法です。
return File(Path.Combine(@"c:\path", fileFromDB.FileNameOnDisk), MimeMapping.GetMimeMapping(fileFromDB.FileName), fileFromDB.FileName);
Phil Haackには、Custome File Download Action Resultクラスを作成したNice の記事 があります。ファイルの仮想パスと名前を付けて保存するだけで構いません。
私はそれを一度使いました、そしてここに私のコードがあります。
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Download(int fileID)
{
Data.LinqToSql.File file = _fileService.GetByID(fileID);
return new DownloadResult { VirtualPath = GetVirtualPath(file.Path),
FileDownloadName = file.Name };
}
私の例では、ファイルの物理パスを保存していたので、このヘルパーメソッドを使用して、仮想パスに変換しました。
private string GetVirtualPath(string physicalPath)
{
string rootpath = Server.MapPath("~/");
physicalPath = physicalPath.Replace(rootpath, "");
physicalPath = physicalPath.Replace("\\", "/");
return "~/" + physicalPath;
}
これがPhill Haackの記事から取ったフルクラスです。
public class DownloadResult : ActionResult {
public DownloadResult() {}
public DownloadResult(string virtualPath) {
this.VirtualPath = virtualPath;
}
public string VirtualPath {
get;
set;
}
public string FileDownloadName {
get;
set;
}
public override void ExecuteResult(ControllerContext context) {
if (!String.IsNullOrEmpty(FileDownloadName)) {
context.HttpContext.Response.AddHeader("content-disposition",
"attachment; filename=" + this.FileDownloadName)
}
string filePath = context.HttpContext.Server.MapPath(this.VirtualPath);
context.HttpContext.Response.TransmitFile(filePath);
}
}
Ian Henryに感謝します。
MS SQL Serverからファイルを取得するためにが必要な場合、これが解決策です。
public FileResult DownloadDocument(string id)
{
if (!string.IsNullOrEmpty(id))
{
try
{
var fileId = Guid.Parse(id);
var myFile = AppModel.MyFiles.SingleOrDefault(x => x.Id == fileId);
if (myFile != null)
{
byte[] fileBytes = myFile.FileData;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, myFile.FileName);
}
}
catch
{
}
}
return null;
}
ここでAppModelはEntityFramework
モデルで、MyFilesはを表します。データベースの)テーブル。 FileDataは、MyFilesテーブルのvarbinary(MAX)
です。
その単純なファイル名でdirectoryPathにあなたの物理的なパスを単に与える
public FilePathResult GetFileFromDisk(string fileName)
{
return File(directoryPath, "multipart/form-data", fileName);
}
public ActionResult Download()
{
var document = //Obtain document from database context
var cd = new System.Net.Mime.ContentDisposition
{
FileName = document.FileName,
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(document.Data, document.ContentType);
}