web-dev-qa-db-ja.com

アクションからファイルを返すときにストリームは破棄されますか?

文字列をMemoryStreamに書き込んでいます。ストリームをコントローラアクションに返して、ダウンロード用のファイルとして送信できるようにする必要があります。

通常、Streamはusingステートメントでラップしますが、この場合は返す必要があります。返品後も廃棄されますか?それとも自分でどうにかして廃棄する必要がありますか?

//inside CsvOutputFormatter
public Stream GetStream(object genericObject)
{
    var stream = new MemoryStream();
    var writer = new StreamWriter(stream, Encoding.UTF8);
    writer.Write(_stringWriter.ToString());
    writer.Flush();
    stream.Position = 0;
    return stream;
}

ファイルを返すコントローラーアクション:

[HttpGet]
[Route("/Discussion/Export")]
public IActionResult GetDataAsCsv()
{
    var forums = _discussionService.GetForums(_userHelper.UserId);

    var csvFormatter = new CsvOutputFormatter(new CsvFormatterOptions());

    var stream = csvFormatter.GetStream(forums);
    return File(stream, "application/octet-stream", "forums.csv");

    //is the stream Disposed here automatically?
}
19

ここのソースコードによると aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc/FileStreamResult.cs

はい

protected override void WriteFile(HttpResponseBase response)
{
    // grab chunks of data and write to the output stream
    Stream outputStream = response.OutputStream;
    using (FileStream)
    {
        byte[] buffer = new byte[BufferSize];

        while (true)
        {
            int bytesRead = FileStream.Read(buffer, 0, BufferSize);
            if (bytesRead == 0)
            {
                // no more data
                break;
            }

            outputStream.Write(buffer, 0, bytesRead);
        }
    }
}

FileStreamは、呼び出し時に渡されたストリームです。

return File(stream, "application/octet-stream", "forums.csv");

更新

あなたの質問は元々Asp.Net MVCとしてタグ付けされていましたが、コードはより新しいコアフレームワークのように見えます。

別の方法で書かれていますが、技術的には同じことを行います。

aspnet/AspNetCore/blob/master/src/Mvc/Mvc.Core/src/Infrastructure/FileResultExecutorBase.cs

protected static async Task WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue range, long rangeLength)
{
    var outputStream = context.Response.Body;
    using (fileStream)
    {
        try
        {
            if (range == null)
            {
                await StreamCopyOperation.CopyToAsync(fileStream, outputStream, count: null, bufferSize: BufferSize, cancel: context.RequestAborted);
            }
            else
            {
                fileStream.Seek(range.From.Value, SeekOrigin.Begin);
                await StreamCopyOperation.CopyToAsync(fileStream, outputStream, rangeLength, BufferSize, context.RequestAborted);
            }
        }
        catch (OperationCanceledException)
        {
            // Don't throw this exception, it's most likely caused by the client disconnecting.
            // However, if it was cancelled for any other reason we need to prevent empty responses.
            context.Abort();
        }
    }
}
15
Nkosi