Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write stream directly to HttpClient

Example flow:

  1. Load file from file system
  2. Modify file by embedding custom id
  3. Send modified file to external system with http.

Current implementation:

public async Task EmbedIdAndSendAsync(string filePath, string id, HttpClient httpClient)
{
    using (Stream stream = File.OpenRead(filePath))
    using (PdfDocument pdf = new PdfDocument(stream))
    using (MemoryStream modifiedStream = new MemoryStream())
    {
        pdf.EmbedId(id);

        pdf.WriteTo(modifiedStream);

        modifiedStream.Position = 0;

        await httpClient.PostAsync(
            "files/upload",
            new MultipartFormDataContent {
                { new StringContent(id), "file[id]" },
                { new StreamContent(modifiedStream), "file[stream]", Path.GetFileName(filePath) }
            }
        );
    }
}

How would I write file modifications directly to HttpClient's network stream without having to use an intermediary memory stream?

like image 866
Linas Avatar asked Dec 09 '25 16:12

Linas


1 Answers

The answer is you have to define your own HttpContent.

In this way you kinda invert the task and HttpClient will call your code when needed and only if needed (because maybe there's no network connection or any other error)

sealed class PdfContent : HttpContent
{
    string filePath;
    string id;

    public PdfContent(string filePath, string id)
    {
        this.filePath = filePath;
        this.id = id;
        // Put something here to define content or just do it in the outer code
        Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    }

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken)
    {
        // Here you can write to a stream directly
        using Stream fileStream = File.OpenRead(filePath);
        using PdfDocument pdf = new PdfDocument(fileStream);
        pdf.EmbedId(id);
        // Use async + cancellationToken if there's one
        pdf.WriteTo(stream);
        return Task.CompletedTask;
    }

    // This is just a technical compatibility override to support cancellation
    protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context)
    {
        return SerializeToStreamAsync(stream, context, CancellationToken.None);
    }

    protected override bool TryComputeLength(out long length)
    {
        // Return something if you know length or zero if not
        length = 0;
        return false;
    }
}

Now just post it.

    await httpClient.PostAsync(
        "files/upload",
        new MultipartFormDataContent {
            { new StringContent(id), "file[id]" },
            { new PdfContent(filePath, id), "file[stream]" }
        }
    );
like image 108
norekhov Avatar answered Dec 11 '25 05:12

norekhov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!