Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 193ea80

Browse files
committed
Moved over SendFileAsync as virtual method on HttpResponse
1 parent 765a520 commit 193ea80

File tree

5 files changed

+84
-114
lines changed

5 files changed

+84
-114
lines changed

src/Microsoft.AspNetCore.Http.Abstractions/HttpResponse.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
using System;
55
using System.IO;
6+
using System.Threading;
67
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Http.Features;
79

810
namespace Microsoft.AspNetCore.Http
911
{
@@ -103,5 +105,80 @@ public abstract class HttpResponse
103105
/// <param name="location">The URL to redirect the client to.</param>
104106
/// <param name="permanent"><c>True</c> if the redirect is permanent (301), otherwise <c>false</c> (302).</param>
105107
public abstract void Redirect(string location, bool permanent);
108+
109+
/// <summary>
110+
/// Sends the given file using the SendFile extension.
111+
/// </summary>
112+
/// <param name="fileName">The full path to the file.</param>
113+
/// <returns></returns>
114+
public virtual Task SendFileAsync(string fileName)
115+
{
116+
if (fileName == null)
117+
{
118+
throw new ArgumentNullException(nameof(fileName));
119+
}
120+
121+
return SendFileAsync(fileName, 0, null, CancellationToken.None);
122+
}
123+
124+
/// <summary>
125+
/// Sends the given file using the SendFile extension.
126+
/// </summary>
127+
/// <param name="fileName">The full path to the file.</param>
128+
/// <param name="offset">The offset in the file.</param>
129+
/// <param name="count">The number of types to send, or null to send the remainder of the file.</param>
130+
/// <param name="cancellationToken"></param>
131+
/// <returns></returns>
132+
public virtual Task SendFileAsync(string fileName, long offset, long? count, CancellationToken cancellationToken = default(CancellationToken))
133+
{
134+
if (fileName == null)
135+
{
136+
throw new ArgumentNullException(nameof(fileName));
137+
}
138+
139+
var sendFile = HttpContext.Features.Get<IHttpSendFileFeature>();
140+
141+
if (sendFile == null)
142+
{
143+
return SendFileAsync(Body, fileName, offset, count, cancellationToken);
144+
}
145+
146+
return sendFile.SendFileAsync(fileName, offset, count, cancellationToken);
147+
}
148+
149+
// Not safe for overlapped writes.
150+
private static async Task SendFileAsync(Stream outputStream, string fileName, long offset, long? length, CancellationToken cancellationToken)
151+
{
152+
cancellationToken.ThrowIfCancellationRequested();
153+
154+
var fileInfo = new FileInfo(fileName);
155+
if (offset < 0 || offset > fileInfo.Length)
156+
{
157+
throw new ArgumentOutOfRangeException(nameof(offset), offset, string.Empty);
158+
}
159+
160+
if (length.HasValue &&
161+
(length.Value < 0 || length.Value > fileInfo.Length - offset))
162+
{
163+
throw new ArgumentOutOfRangeException(nameof(length), length, string.Empty);
164+
}
165+
166+
int bufferSize = 1024 * 16;
167+
168+
var fileStream = new FileStream(
169+
fileName,
170+
FileMode.Open,
171+
FileAccess.Read,
172+
FileShare.ReadWrite,
173+
bufferSize: bufferSize,
174+
options: FileOptions.Asynchronous | FileOptions.SequentialScan);
175+
176+
using (fileStream)
177+
{
178+
fileStream.Seek(offset, SeekOrigin.Begin);
179+
180+
await StreamCopyOperation.CopyToAsync(fileStream, outputStream, length, cancellationToken);
181+
}
182+
}
106183
}
107184
}

src/Microsoft.AspNetCore.Http.Extensions/StreamCopyOperation.cs renamed to src/Microsoft.AspNetCore.Http.Abstractions/StreamCopyOperation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
using System.Threading;
99
using System.Threading.Tasks;
1010

11-
namespace Microsoft.AspNetCore.Http.Extensions
11+
namespace Microsoft.AspNetCore.Http
1212
{
1313
// FYI: In most cases the source will be a FileStream and the destination will be to the network.
1414
public static class StreamCopyOperation

src/Microsoft.AspNetCore.Http.Abstractions/project.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"type": "build",
1616
"version": "1.0.0-*"
1717
},
18-
"System.Text.Encodings.Web": "4.0.0-*"
18+
"System.Text.Encodings.Web": "4.0.0-*",
19+
"System.Buffers": "4.0.0-*"
1920
},
2021
"frameworks": {
2122
"net451": {
@@ -32,7 +33,8 @@
3233
"System.Net.WebSockets": "4.0.0-*",
3334
"System.Reflection.TypeExtensions": "4.1.0-*",
3435
"System.Runtime.InteropServices": "4.0.21-*",
35-
"System.Security.Cryptography.X509Certificates": "4.0.0-*"
36+
"System.Security.Cryptography.X509Certificates": "4.0.0-*",
37+
"System.IO.FileSystem": "4.0.1-*"
3638
}
3739
}
3840
}

src/Microsoft.AspNetCore.Http.Extensions/SendFileResponseExtensions.cs

Lines changed: 0 additions & 104 deletions
This file was deleted.

src/Microsoft.AspNetCore.Http.Extensions/project.json

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,10 @@
1111
},
1212
"dependencies": {
1313
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0-*",
14-
"Microsoft.Net.Http.Headers": "1.0.0-*",
15-
"System.Buffers": "4.0.0-*"
14+
"Microsoft.Net.Http.Headers": "1.0.0-*"
1615
},
1716
"frameworks": {
1817
"net451": {},
19-
"dotnet5.4": {
20-
"dependencies": {
21-
"System.IO.FileSystem": "4.0.1-*"
22-
}
23-
}
18+
"dotnet5.4": { }
2419
}
2520
}

0 commit comments

Comments
 (0)