アクションからファイルを返すには、次のようにします。
return File(myStream, ...);
これは、using ステートメントでラップできないことを意味myStream
し、悲しいことです。返したいファイルの中身にたどり着くために、ステートメントを使用する際に複数のことがあったとします。たとえば、SQL Filestream として格納されているデータベースからファイルを返しています。
using (SqlConnection connection = ...)
{
using (SqlTransaction trans = ...)
{
using (SqlFileStream fileStream = ...)
{
return File(fileStream, ...);
}
}
}
ファイルがストリーミングされた後、ストリーム、トランザクション、および接続がすべて閉じられるように、using ステートメント内でこれを実行したいと考えています。もちろん、それはできません。return ステートメントが実行されるとすぐに、使用しているすべてのものが閉じられるからです。送信先のストリームFile(...)
が閉じられることは認識していますが、他のものは (理論上) 開いたままになります。
私の解決策はこれです:
SqlConnection connection = ...;
SqlTransaction trans = ...;
SqlFileStream fileStream = ...;
return new DisposableFileStreamResult(fileStream, MimeMapping.GetMimeMapping(file.Name), file.Name, () =>
{
fileStream.Dispose(); //It's already disposed but for clarity...
trans.Dispose();
connection.Dispose();
});
DisposableFileStreamResult は次のようになります。
public class DisposableFileStreamResult : FileStreamResult
{
public Action Cleanup { get; set; }
public DisposableFileStreamResult(Stream stream, string contentType) : this(stream, contentType, null) { }
public DisposableFileStreamResult(Stream stream, string contentType, string fileDownloadName) : this(stream, contentType, fileDownloadName, null) { }
public DisposableFileStreamResult(Stream stream, string contentType, string fileDownloadName, Action cleanup)
: base(stream, contentType)
{
base.FileDownloadName = fileDownloadName;
this.Cleanup = cleanup;
}
protected override void WriteFile(HttpResponseBase response)
{
base.WriteFile(response);
if (this.Cleanup != null)
this.Cleanup();
}
}
たくさんのものをメモリに読み込みたくありません。バイト配列は好きじゃない! MVC4 を使用してこれを行う組み込みの方法はありますか? 大きなファイルを返却する必要がある場合はどうすればよいですか? 私の一時的な解決策は合理的なものですか、それともやり過ぎですか、それとも必要ではありませんか?