文字列を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?
}
ここのソースコードによると 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();
}
}
}