aspnetcore/test/WebSites/FilesWebSite/SendFileMiddleware.cs

73 lines
2.5 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.Extensions.PlatformAbstractions;
namespace FilesWebSite
{
public class SendFileMiddleware
{
private const int DefaultBufferSize = 0x1000;
private readonly RequestDelegate _next;
public SendFileMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
var environment = (IApplicationEnvironment)context.RequestServices.GetService(typeof(IApplicationEnvironment));
if (context.Features.Get<IHttpSendFileFeature>() == null)
{
var sendFile = new SendFileFallBack(context.Response.Body, environment.ApplicationBasePath);
context.Features.Set<IHttpSendFileFeature>(sendFile);
}
await _next(context);
}
private class SendFileFallBack : IHttpSendFileFeature
{
private readonly string _appBasePath;
private Stream _responseStream;
public SendFileFallBack(Stream responseStream, string appBasePath)
{
_responseStream = responseStream;
_appBasePath = appBasePath;
}
public async Task SendFileAsync(string path, long offset, long? length, CancellationToken cancellation)
{
using (var stream = new FileStream(Path.Combine(_appBasePath, path), FileMode.Open))
{
length = length ?? stream.Length - offset;
stream.Seek(offset, SeekOrigin.Begin);
var bufferSize = length < DefaultBufferSize ? length.Value : DefaultBufferSize;
var buffer = new byte[bufferSize];
var bytesRead = 0;
do
{
var bytesToRead = bufferSize < length ? bufferSize : length;
bytesRead = await stream.ReadAsync(buffer, 0, (int)bytesToRead);
length = length - bytesRead;
await _responseStream.WriteAsync(buffer, 0, bytesRead);
} while (bytesRead > 0 && length > 0);
}
}
}
}
}