Skip to content

Instantly share code, notes, and snippets.

@SlyNet
Created November 9, 2018 10:24
Show Gist options
  • Save SlyNet/d3fe78140d91165f351110e6ab1ae4df to your computer and use it in GitHub Desktop.
Save SlyNet/d3fe78140d91165f351110e6ab1ae4df to your computer and use it in GitHub Desktop.
Progressive download response message for asp.net webapi that supports video streaming and partial download and not broken
public class ProgressiveDownload
{
private readonly HttpRequestMessage request;
public ProgressiveDownload(HttpRequestMessage request)
{
this.request = request;
}
public HttpResponseMessage HeaderInfoMessage(long contentLength, string mediaType)
{
var response = this.request.CreateResponse();
response.Content = new ByteArrayContent(Array.Empty<byte>());
response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(mediaType);
response.Content.Headers.ContentLength = contentLength;
response.Headers.AcceptRanges.Add("bytes");
return response;
}
public HttpResponseMessage ResultMessage(Stream stream, string mediaType)
{
var rangeHeader = this.request.Headers.Range?.Ranges.FirstOrDefault();
if (rangeHeader != null)
{
var byteRange = new ByteRangeStreamContent(stream, this.request.Headers.Range, mediaType);
var partialResponse = this.request.CreateResponse(HttpStatusCode.PartialContent);
partialResponse.Content = new PushStreamContent((outputStream, content, context) =>
{
try
{
stream.Seek(rangeHeader.From ?? 0, SeekOrigin.Begin);
long bufferSize = 32 * 1024;
byte[] buffer = new byte[bufferSize];
while (true)
{
if (rangeHeader.To != null)
{
bufferSize = Math.Min(bufferSize, rangeHeader.To.Value - stream.Position);
}
int count = stream.Read(buffer, 0, (int) bufferSize);
if (count != 0)
outputStream.Write(buffer, 0, count);
else
break;
}
}
catch (HttpException)
{
}
finally
{
outputStream.Close();
}
});
partialResponse.Content.Headers.ContentType = byteRange.Headers.ContentType;
partialResponse.Content.Headers.ContentLength = byteRange.Headers.ContentLength;
partialResponse.Content.Headers.ContentRange = byteRange.Headers.ContentRange;
return partialResponse;
}
var nonPartialResponse = this.request.CreateResponse(HttpStatusCode.OK);
nonPartialResponse.Content = new StreamContent(stream);
nonPartialResponse.Content.Headers.ContentType = new MediaTypeHeaderValue(mediaType);
return nonPartialResponse;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment