Open Closed

IRemoteStreamContent - Download Large Files #9354


User avatar
0
kkmy created

Hello,

I have a big zip file in the server (5GB). I am trying to send the file to the front end so that the user can download it.

return new RemoteStreamContent(zipFileStream, zipFileName, FileTypes.Zip.ContentType);

This approach works for moderate files, however gives an error for big files.

2025-05-22 12:07:54.247 +03:00 [ERR] Stream was too long.
System.IO.IOException: Stream was too long.
   at System.IO.MemoryStream.WriteAsync(ReadOnlyMemory`1 buffer, CancellationToken cancellationToken)
--- End of stack trace from previous location ---
   at System.IO.Stream.<CopyToAsync>g__Core|27_0(Stream source, Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
   at System.IO.Strategies.BufferedFileStreamStrategy.CopyToAsyncCore(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
   at Volo.Abp.AspNetCore.Mvc.ContentFormatters.RemoteStreamContentOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|28_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at IPS.IPSHttpApiHostModule.<>c.<<OnApplicationInitialization>b__12_0>d.MoveNext() in C:\eld-vm-01-b1\_work\27\s\src\IPS.HttpApi.Host\IPSHttpApiHostModule.cs:line 359
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Volo.Abp.AspNetCore.Security.Claims.AbpDynamicClaimsMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.Uow.AbpUnitOfWorkMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)

What should be the approach for big files?

Thank you.


13 Answer(s)
  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Hi, ABP’s RemoteStreamContent is great for lightweight files or when you want to abstract things but it’s not designed for very large files. It attempts to copy the stream into an in-memory buffer (MemoryStream), which crashes for files >2GB or causes heavy memory usage.

    So, for large files, instead, you can use FileStream (see https://stackoverflow.com/a/39890811/10477283) and FileStreamResult.

  • User Avatar
    0
    kkmy created

    Is there an example for this? Because I have written it like the following:

    public async Task< **FileStreamResult** > ExportAsync()
    {
        ...
        
        return new FileStreamResult(zipFileStream, FileTypes.Zip.ContentType);
    }
    

    However, proxy generation is failed:

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I am trying to send the file to the front end so that the user can download it.

    Please share your full app service code.

    Thanks.

  • User Avatar
    0
    kkmy created
    public async Task< FileStreamResult > ExportAsync(ExportDto input)
    {
        var contents = new Dictionary<string, byte[]>();
        var discardedContents = new Dictionary<string, byte[]>();
    
        FillMuyCompressionItems(ref contents, ref discardedContents);
        FillMlCompressionItems(ref contents, ref discardedContents);
        FillAkbCompressionItems(ref contents, ref discardedContents);
        FillCkCompressionItems(ref contents, ref discardedContents);
    
        var zipFileName = "EXPORT.zip";
    
        var mainZipFileStream = new FileStream(Path.Join(Path.GetTempPath(), zipFileName), FileMode.Create, FileAccess.ReadWrite);
    
        using (var zipArchive = new ZipArchive(mainZipFileStream, ZipArchiveMode.Create, true))
        {        
            for (var i = 0; i < contents.Count; i++)
            {
                var item = contents.ElementAt(i);
            
                var originalFileStream = new FileStream(Path.Join(Path.GetTempPath(), item.Key), FileMode.Create, FileAccess.ReadWrite);
                await originalFileStream.WriteAsync(item.Value);
                originalFileStream.Seek(0, SeekOrigin.Begin);
            
                var zipEntry = zipArchive.CreateEntry(item.Key, CompressionLevel.Fastest);
    
                await using(var zipEntryStream = zipEntry.Open())
                await using (originalFileStream)
                {
                    await originalFileStream.CopyToAsync(zipEntryStream);
                }
            }
        }
    
        mainZipFileStream.Seek(0, SeekOrigin.Begin);
    
        return new FileStreamResult(mainZipFileStream, FileTypes.Zip.ContentType);
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you also share the code of IRemoteStreamContent version? Thanks

  • User Avatar
    0
    kkmy created
    public async Task< IRemoteStreamContent > ExportAsync(ExportDto input)
    {
        var contents = new Dictionary<string, byte[]>();
        var discardedContents = new Dictionary<string, byte[]>();
    
        FillMuyCompressionItems(ref contents, ref discardedContents);
        FillMlCompressionItems(ref contents, ref discardedContents);
        FillAkbCompressionItems(ref contents, ref discardedContents);
        FillCkCompressionItems(ref contents, ref discardedContents);
    
        var zipFileName = "EXPORT.zip";
    
        var mainZipFileStream = new FileStream(Path.Join(Path.GetTempPath(), zipFileName), FileMode.Create, FileAccess.ReadWrite);
    
        using (var zipArchive = new ZipArchive(mainZipFileStream, ZipArchiveMode.Create, true))
        {
            for (var i = 0; i < contents.Count; i++)
            {
                var item = contents.ElementAt(i);
                
                using var originalFileStream = new MemoryStream(item.Value);
    
                var zipEntry = zipArchive.CreateEntry(item.Key, CompressionLevel.Fastest);
    
                await using var zipEntryStream = zipEntry.Open();
    
                await originalFileStream.CopyToAsync(zipEntryStream);
            }
        }
    
        mainZipFileStream.Seek(0, SeekOrigin.Begin);
    
        return new RemoteStreamContent(mainZipFileStream, zipFileName, FileTypes.Zip.ContentType);
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Thanks. Do you have app.UseAbpStudioLink(); in your IPSHttpApiHostModule.cs?

    If so, Please remove it and use IRemoteStreamContent again.

  • User Avatar
    0
    kkmy created

    It worked perfectly, thank you so much!

    Though, I really wonder what is the corelation between AbpStudioLink and IRemoteStreamContent if it is not a secret? :) What makes it does not work?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    AbpStudioLink will use MemoryStream; We will fix it in the next version.

    Thanks.

  • User Avatar
    0
    kkmy created

    Oh I see!

    Does this mean that it is better to add app.UseAbpStudioLink(); again after the next version? Or let it be removed like this?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can use it in the next version. remove it now. ; )

  • User Avatar
    0
    kkmy created

    Got it!

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Great

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.3.0-preview. Updated on June 13, 2025, 11:37