Stream asset downloads to avoid OutOfMemoryException on large files (#1540)
Some checks are pending
docker / pack (push) Waiting to run
docker / deploy (push) Waiting to run
main / format (push) Waiting to run
main / test (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-arm) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-arm64) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-musl-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, osx-arm64) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, osx-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, win-arm64) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, win-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Cli, DiscordChatExporter.Cli, win-x86) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, linux-arm) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, linux-arm64) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, linux-musl-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, linux-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, osx-arm64) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, osx-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, win-arm64) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, win-x64) (push) Waiting to run
main / pack (DiscordChatExporter.Gui, DiscordChatExporter, win-x86) (push) Waiting to run
main / release (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-arm) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-arm64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-musl-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, linux-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, osx-arm64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, osx-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, win-arm64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, win-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Cli, DiscordChatExporter.Cli, win-x86) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, linux-arm) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, linux-arm64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, linux-musl-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, linux-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, osx-arm64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, osx-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, win-arm64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, win-x64) (push) Blocked by required conditions
main / deploy (DiscordChatExporter.Gui, DiscordChatExporter, win-x86) (push) Blocked by required conditions
main / notify (push) Blocked by required conditions

* 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.

* Update ExportAssetDownloader.cs

---------

Co-authored-by: Oleksii Holub <1935960+Tyrrrz@users.noreply.github.com>
This commit is contained in:
Colton 2026-06-03 05:47:43 -07:00 committed by GitHub
parent 64a4ba296e
commit 799dd1ad81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net.Http;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -64,7 +65,14 @@ internal partial class ExportAssetDownloader(string workingDirPath, bool reuse)
async innerCancellationToken => async innerCancellationToken =>
{ {
// Download the file // Download the file
using var response = await Http.Client.GetAsync(url, innerCancellationToken); using var response = await Http.Client.GetAsync(
url,
HttpCompletionOption.ResponseHeadersRead,
innerCancellationToken
);
response.EnsureSuccessStatusCode();
await using var output = File.Create(filePath); await using var output = File.Create(filePath);
await response.Content.CopyToAsync(output, innerCancellationToken); await response.Content.CopyToAsync(output, innerCancellationToken);
}, },