Streaming with AspNetCore
See original GitHub issueHas anyone found a better way to stream file? Here is what I came up with:
//http://localhost:5000/Youtube/Download/bcQQwYKkj_s
[Route("Youtube")]
public class YoutubeController : ControllerBase {
[HttpGet("Download/{id}")]
public async Task DownloadAudio(string id) {
var client = new YoutubeClient();
var mediaInfoSet = await client.GetVideoMediaStreamInfosAsync(id);
var mediaStreamInfo = mediaInfoSet.Audio.WithHighestBitrate();
var contentType = mediaStreamInfo is AudioStreamInfo ? "audio" : "video"; //With this example just put "audio" I use custom query parameters ;)
HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={id}.{mediaStreamInfo.Container}");
HttpContext.Response.Headers.Add("Content-Type", $"{contentType}/{mediaStreamInfo.Container}");
await client.DownloadMediaStreamAsync(mediaStreamInfo, HttpContext.Response.Body, null);
}
}
Maybe among you there is an AspNet Core guru and knows better way to do this? If No I would probably put this into examples (so I could find this later myself 😄).
I couldn’t work it out with Task<ActionResult<FileStreamResult>>
so had to do all header stuff manually.
Edit: I found a better solution for this, which allows returning IActionResult
, this allows return BadRequest(...)
if you do for example:
if (!ModelState.IsValid) {
return BadRequest(ModelState);
}
Here is my better solution:
[Route("Youtube")]
public class YoutubeController : ControllerBase {
[HttpGet("Download/{id}")]
public IActionResult DownloadAudio(string id) {
//TODO: validate id
var client = new YoutubeClient(); //This should be initialized in YoutubeController constructor.
return new StreamYoutubeVideo(client, id);
}
}
public class StreamYoutubeVideo : ActionResult {
private readonly IYoutubeClient _client;
private readonly string _videoId;
public StreamYoutubeVideo(IYoutubeClient client, string videoId) {
_client = client;
_videoId = videoId;
}
public override async Task ExecuteResultAsync(ActionContext context) {
var mediaInfoSet = await _client.GetVideoMediaStreamInfosAsync(_videoId);
var mediaStreamInfo = mediaInfoSet.Audio.WithHighestBitrate();
context.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={_videoId}.{mediaStreamInfo.Container.GetFileExtension()}");
context.HttpContext.Response.Headers.Add("Content-Type", $"audio/{mediaStreamInfo.Container.GetFileExtension()}");
await _client.DownloadMediaStreamAsync(mediaStreamInfo, context.HttpContext.Response.Body);
}
}
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (5 by maintainers)
Top Results From Across the Web
Request and Response operations in ASP.NET Core
ASP.NET Core is starting to use pipelines instead of streams internally. Examples include: FormReader; TextReader; TextWriter; HttpResponse.
Read more >ASP.NET Core in .NET 6 - Async streaming
This is the next part of the ASP.NET Core on .NET 6 series. In this post, I'd like to have a look into...
Read more >How to stream with ASP.NET Core
To stream a response that should appear to the browser like a downloaded file, you should use FileStreamResult :
Read more >Stream large content from ASP.NET Core - elmah.io Blog
Learn how to stream a large response from an ASP.NET Core web application to the browser without the risk of throwing an ...
Read more >Video Streaming in HTML5
This repo shows how you can add Video Streaming to your ASP.NET Core App. Table of Contents. Understanding Video Streaming; Video Content Preparation...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
vscode, noice 😎
Regarding your edited version, I recommend using
mediaStreamInfo.Container.GetFileExtension()
, this will return the actual extension instead of enum name (which can theoretically change).