Undo use of pipewriter in FileBufferingWriteStream (#21833)
This commit is contained in:
parent
0e652d1aba
commit
48261fdada
|
|
@ -77,8 +77,6 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||
public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
|
||||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||
public System.Threading.Tasks.Task DrainBufferAsync(System.IO.Pipelines.PipeWriter destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
|
||||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||
public System.Threading.Tasks.Task DrainBufferAsync(System.IO.Stream destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
|
||||
public override void Flush() { }
|
||||
public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
|
||||
|
|
|
|||
|
|
@ -186,25 +186,8 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
// unspooled content. Copy the FileStream content first when available.
|
||||
if (FileStream != null)
|
||||
{
|
||||
// We make a new stream for async reads from disk and async writes to the destination
|
||||
await using var readStream = new FileStream(FileStream.Name, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite, bufferSize: 1, useAsync: true);
|
||||
await FileStream.FlushAsync(cancellationToken);
|
||||
|
||||
await readStream.CopyToAsync(destination, cancellationToken);
|
||||
|
||||
// This is created with delete on close
|
||||
await FileStream.DisposeAsync();
|
||||
FileStream = null;
|
||||
}
|
||||
|
||||
await PagedByteBuffer.MoveToAsync(destination, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task DrainBufferAsync(PipeWriter destination, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// When not null, FileStream always has "older" spooled content. The PagedByteBuffer always has "newer"
|
||||
// unspooled content. Copy the FileStream content first when available.
|
||||
if (FileStream != null)
|
||||
{
|
||||
// We make a new stream for async reads from disk and async writes to the destination
|
||||
await using var readStream = new FileStream(FileStream.Name, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite, bufferSize: 1, useAsync: true);
|
||||
|
||||
|
|
|
|||
|
|
@ -371,6 +371,24 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
Assert.Equal(0, bufferingStream.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DrainBufferAsync_IncludesContentPossiblyBufferedByFileStream()
|
||||
{
|
||||
// We want to ensure that the FileStream (which has a 1-byte buffer) flushes prior to the other read stream reading input.
|
||||
// Arrange
|
||||
var input = new byte[] { 3, };
|
||||
using var bufferingStream = new FileBufferingWriteStream(0, tempFileDirectoryAccessor: () => TempDirectory);
|
||||
bufferingStream.Write(input, 0, input.Length);
|
||||
var memoryStream = new MemoryStream();
|
||||
|
||||
// Act
|
||||
await bufferingStream.DrainBufferAsync(memoryStream, default);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(input, memoryStream.ToArray());
|
||||
Assert.Equal(0, bufferingStream.Length);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
if (fileBufferingWriteStream != null)
|
||||
{
|
||||
response.ContentLength = fileBufferingWriteStream.Length;
|
||||
await fileBufferingWriteStream.DrainBufferAsync(response.BodyWriter);
|
||||
await fileBufferingWriteStream.DrainBufferAsync(response.Body);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
if (fileBufferingWriteStream != null)
|
||||
{
|
||||
response.ContentLength = fileBufferingWriteStream.Length;
|
||||
await fileBufferingWriteStream.DrainBufferAsync(response.BodyWriter);
|
||||
await fileBufferingWriteStream.DrainBufferAsync(response.Body);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
|
|
@ -154,15 +154,17 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Equal(expected, await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public virtual async Task Formatting_LargeObject()
|
||||
[Theory]
|
||||
[InlineData(65 * 1024)]
|
||||
[InlineData(2 * 1024 * 1024)]
|
||||
public virtual async Task Formatting_LargeObject(int size)
|
||||
{
|
||||
// Arrange
|
||||
var expectedName = "This is long so we can test large objects " + new string('a', 1024 * 65);
|
||||
var expectedName = "This is long so we can test large objects " + new string('a', size);
|
||||
var expected = $"{{\"id\":10,\"name\":\"{expectedName}\",\"streetName\":null}}";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync($"/JsonOutputFormatter/{nameof(JsonOutputFormatterController.LargeObjectResult)}");
|
||||
var response = await Client.GetAsync($"/JsonOutputFormatter/{nameof(JsonOutputFormatterController.LargeObjectResult)}/{size}");
|
||||
|
||||
// Assert
|
||||
await response.AssertStatusCodeAsync(HttpStatusCode.OK);
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ namespace FormatterWebSite.Controllers
|
|||
["Key3"] = null,
|
||||
};
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<SimpleModel> LargeObjectResult() =>
|
||||
[HttpGet("{size:int}")]
|
||||
public ActionResult<SimpleModel> LargeObjectResult(int size) =>
|
||||
new SimpleModel
|
||||
{
|
||||
Id = 10,
|
||||
Name = "This is long so we can test large objects " + new string('a', 1024 * 65),
|
||||
Name = "This is long so we can test large objects " + new string('a', size),
|
||||
};
|
||||
|
||||
[HttpGet]
|
||||
|
|
|
|||
Loading…
Reference in New Issue