Stream asset downloads to avoid OutOfMemoryException on large files

ExportAssetDownloader used HttpClient.GetAsync(url, ct), which defaults to
HttpCompletionOption.ResponseContentRead and buffers the entire response body
into memory before returning. Downloading a large attachment therefore tried to
grow a single in-memory buffer to the full file size and threw
OutOfMemoryException (HttpContent.LoadIntoBufferAsync -> GrowAndWrite).

Pass HttpCompletionOption.ResponseHeadersRead so the body is streamed straight
to disk via CopyToAsync in bounded chunks, matching how DiscordClient already
issues its requests.
This commit is contained in:
265866 2026-06-01 19:52:44 -07:00
parent 45629c9d7f
commit e7a9499601

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
@ -63,8 +64,15 @@ internal partial class ExportAssetDownloader(string workingDirPath, bool reuse)
await Http.ResiliencePipeline.ExecuteAsync(
async innerCancellationToken =>
{
// Download the file
using var response = await Http.Client.GetAsync(url, innerCancellationToken);
// Download the file.
// Use ResponseHeadersRead so the response body is streamed to disk instead of
// being fully buffered into memory first, which can cause an OutOfMemoryException
// on large attachments.
using var response = await Http.Client.GetAsync(
url,
HttpCompletionOption.ResponseHeadersRead,
innerCancellationToken
);
await using var output = File.Create(filePath);
await response.Content.CopyToAsync(output, innerCancellationToken);
},