locked
Returning a mp3 file trough File Action results, stops after being played for 10 minutes RRS feed

  • Question

  • User-585144208 posted

    I have an action that returns mp3 file as below : 

                    var memory = new MemoryStream();
                    using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        await stream.CopyToAsync(memory);
                    }
                    memory.Position = 0;
    
                    //Response.Headers.Add("Accept-Ranges", "bytes");
                    //Response.Headers.Add("Connection", "keep-alive");
    
                    return File(memory, "audio/mpeg", $"music.mp3", true);

    So the is partial content. After 10 minutes of playing the mp3 file by calling my action, the player stops. I saw that html default player has logged following error in the browser console :

    " net::ERR_CONNECTION_RESET 206 (Partial Content)"

    What would be the reason ? 

    Sunday, March 8, 2020 6:08 PM

All replies

  • User503812343 posted

    check the HTTP header "Content-length" value. It should not have multiple values or there should not be multiple http headers with name "content-length".

    Monday, March 9, 2020 3:10 AM
  • User711641945 posted

    Hi b.dev,

    I could not reproduce your issue by using your code.By using the code,the browser will download the file named music.mp3 and it could play to the end(the mp3 is over 10 minutes) successfuly by the player.

    What is your version of asp.net core?Could you share more details which could reproduce your issue?

    Here are some github issue about `ERR_CONNECTION_RESET 206` you could refer to:

    https://github.com/aspnet/Mvc/pull/6895#issuecomment-356477675

    https://stackoverflow.com/a/35920244/11398810

    Best Regards,

    Rena

    Monday, March 9, 2020 8:01 AM
  • User-585144208 posted

    Hi Rena

    The asp.net core version I am using is 2.2

    Consider that the file is begin played through a music player and it uses partial content to load the music. 

    Monday, March 9, 2020 9:09 AM
  • User-585144208 posted

    Hi l.laxmikant

    How can I check if "Content-length" has multiple values ?

    Monday, March 9, 2020 9:09 AM
  • User503812343 posted

    Monday, March 9, 2020 11:32 AM
  • User-585144208 posted

    Did you read my question carefully ? I already know that with network tab on browser or tools like fiddler I can access "content-length" !

    The file which is being served is played through a player, either through html player or a music player in mobile app.

    By taking a look at network requests in browser, I see there are multiple requests to end point which is returning the file, because it is served as partial content. 

    Do you know any thing about partial content ? 

    My question is how can I know that the "content-length" could have multiple values. 

    Monday, March 9, 2020 12:01 PM
  • User475983607 posted

    As far I can determine from the code shown, you're design very simply returns the entire file to the audio client.   I call this a "hopeful" design as you are hoping the design will work with the audio client you selected.  My best guess is you need to support ranges.  I recommend reading the support docs for the audio player client you are using.

    Monday, March 9, 2020 12:26 PM
  • User753101303 posted

    AFAIK it doesn't work this way. You should see a range header that asks for a given byte range and the server should then return just that with a single value for content-length). See https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests

    Not sure if related but my first move would be to use https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.physicalfile?view=aspnetcore-3.1#Microsoft_AspNetCore_Mvc_ControllerBase_PhysicalFile_System_String_System_String_System_Boolean_ instead. Internally it should return the relevant file portion.

    For now you are always loading the full file in memory and I wonder if it couldn't end up with causing an issue. You don't have any error server side or can you see some http status in addition to this ERR_CONNECTION_RESET message ? (wonder if you could have an http 500)

    Monday, March 9, 2020 12:57 PM
  • User-585144208 posted

    This is what player sents in request:  

    Range: bytes=0-  

    and here is the network request response headers  

    Status Code: 206 Partial Content

    Accept-Ranges: bytes Content-Disposition:

    attachment; filenamea.mp3; filename*=UTF-8''a.mp3

    Content-Length: 16670764

    Content-Range: bytes 0-16670763/16670764  

    The application is running locally, and when  net::ERR_CONNECTION_RESET 206 happened, there was not any debug break in the Visual studio to see any error. a

    Monday, March 9, 2020 9:19 PM
  • User475983607 posted

    b.dev

    This is what player sents in request:  

    Range: bytes=0-  

    and here is the network request response headers  

    Status Code: 206 Partial Content

    Accept-Ranges: bytes Content-Disposition:

    attachment; filenamea.mp3; filename*=UTF-8''a.mp3

    Content-Length: 16670764

    Content-Range: bytes 0-16670763/16670764  

    The application is running locally, and when  net::ERR_CONNECTION_RESET 206 happened, there was not any debug break in the Visual studio to see any error. a

    Right.  Your code does not support ranges as explained twice above.  You need to learn the basics by reading the links provided if you intend to handle serving the file using code.  Otherwise, let the static file handler serve the mp3.

    Monday, March 9, 2020 9:30 PM
  • User-585144208 posted

    if it does not accept ranges, why it returns 

    Accept-Ranges and Content-Range in header ? 

    Monday, March 9, 2020 9:32 PM
  • User475983607 posted

    b.dev

    if it does not accept ranges, why it returns 

    Accept-Ranges and Content-Range in header ? 

    You're asking about the HTTP request?  The response is an error, correct?  You - the developer - are responsible for the response.   Otherwise, share your code that handles ranges.

    Monday, March 9, 2020 9:34 PM
  • User-585144208 posted

    Read my answer again before blindly replying :

    "and here is the network request response headers "

    I have said it is the response header for the network request !!!

    Monday, March 9, 2020 9:36 PM
  • User711641945 posted

    Hi b.dev,

    Add the following code to your Program.cs:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
            AppContext.SetSwitch("Switch.Microsoft.AspNetCore.Mvc.EnableRangeProcessing", true);
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

    Best Regards,

    Rena

    Tuesday, March 10, 2020 8:11 AM
  • User753101303 posted

    And the size of the file is 16670764  bytes? For now my understanding is that the plaer asks for the full file and the server returns the full file.

    (based on https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range)

    Edit: if the previous response doesn't help, try also to use an overload without the file name to avoid sending the attachment content-disposition in case it would interfere ??

    Tuesday, March 10, 2020 12:47 PM
  • User-585144208 posted

    By using the overload without filename, the Range in header request is no more 0, but Content-length is changed in the second request (second range of bytes to request from the server to play the music.) Still the net::ERR_CONNECTION_RESET 206 (Partial Content) appears. 

    Tuesday, March 10, 2020 10:00 PM
  • User711641945 posted

    Hi b.dev,

    Here is my whole working demo,you could try it in your project:

    1.Index.cshtml:

    <video autoplay controls src="/Home/Play"></video>
    

    2.Controller:

    public IActionResult Index()
    {
        return View();
    }
    public async Task<FileStreamResult> Play()
    {
        var memory = new MemoryStream();
        using (var stream = new FileStream("test.mp3", FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            await stream.CopyToAsync(memory);
        }
        memory.Position = 0;
        return File(memory, "audio/mpeg", $"music.mp3", true);
    }

    3.Program.cs:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
            AppContext.SetSwitch("Switch.Microsoft.AspNetCore.Mvc.EnableRangeProcessing", true);
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

    If you still makes error,could you share your code which could reproduce your issue?

    Best Regards,

    Rena

    Friday, March 13, 2020 8:22 AM
  • User-1749909477 posted

    Kindly read the support docs for the mp3 audio player client you are currently using to fix the issue. I think that should help.

    Wednesday, May 13, 2020 7:34 PM