Embedding Local Images using Data URIs

    HTML that references local images by file path, such as <img src="C:\Reports\chart-1.png">, only renders correctly on the machine where that file exists. The moment your app needs to move that HTML - store it in a database column, send it by email, or render it on a different machine or server - the local image is unreachable and the picture is simply gone. The WinForms HTML Editor can avoid that failure mode entirely. This page shows how to make an image travel with its HTML instead of depending on a file path that may not exist wherever the HTML ends up.

    Making the HTML self-contained

    The fix is to fold the image bytes directly into the HTML as a data URI - <img src="data:image/png;base64,iVBORw0K..."> - instead of a file path. After the conversion, the HTML stands alone: store it in a database column, attach it to an email, or copy it to another machine, and the images travel with it because they are part of it.

    An <img src=> pointing at a local file path only works on the machine that has that file. Save the HTML to a database, email it, or host it on a server, and the image is gone the moment it leaves the original machine. EmbedLocalImagesAsBase64() rewrites every local image reference into a self-contained data: URI, so the HTML carries its own images and needs no external file at all.

    Before: local file reference
    <p>Q3 revenue trended up across all three regions.</p> <img src="C:\Users\priya\Reports\acme-q3\chart-1.png" alt="Q3 revenue by region">
    After: EmbedLocalImagesAsBase64() applied
    <p>Q3 revenue trended up across all three regions.</p> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAGQCAYAAAB...(truncated, several KB of encoded pixel data follows)..." alt="Q3 revenue by region">

    The file path is gone; the image bytes themselves are now part of the markup string returned by DocumentHtml. That string can be stored in a database column, dropped into an HtmlBody on a MailMessage, or written straight to a static file - it renders identically everywhere, with zero dependency on the machine that authored it.

    The helper

    On editor.Content (an IContentService):

    void EmbedLocalImagesAsBase64();

    The helper walks the document's <img> elements. For each one whose src is a local file path, it reads the bytes, infers the MIME type from the file extension (image/png, image/jpeg, image/gif, image/webp, etc.), Base64-encodes the bytes, and rewrites the src in place to the equivalent data: URI. Remote URLs (http://, https://) are left untouched, so an image hosted elsewhere can sit alongside local screenshots.

    The rewrite happens in the editor's in-memory document. After the call returns, editor.Content.GetBodyHtml(true) and editor.Content.GetDocumentHtml() reflect the new state. Read the HTML out of either of those.

    The fixed save path

    private async Task SaveReportAsync(Guid reportId) {     // 1. Fold local images into the HTML in place.     //    After this call, every <img src="C:\..."> has become     //    <img src="data:image/...;base64,...">.     htmlEditor1.Content.EmbedLocalImagesAsBase64();     // 2. Read the rewritten body HTML out of the editor.     string body = htmlEditor1.Content.GetBodyHtml(getInXhtml: true);     // 3. Persist. One column. One round trip.     await _reports.UpdateBodyAsync(reportId, body); }
    Private Async Function SaveReportAsync(reportId As Guid) As Task     ' 1. Fold local images into the HTML in place.     '    After this call, every <img src="C:\..."> has become     '    <img src="data:image/...;base64,...">.     htmlEditor1.Content.EmbedLocalImagesAsBase64()     ' 2. Read the rewritten body HTML out of the editor.     Dim body As String = htmlEditor1.Content.GetBodyHtml(getInXhtml:=True)     ' 3. Persist. One column. One round trip.     Await _reports.UpdateBodyAsync(reportId, body) End Function

    The saved HTML is self-contained: it renders correctly wherever it is opened, and the rendering machine never needs access to the original image files.

    Self-contained consulting client report rendered in a web portal: all embedded screenshots load from base64 data URIs inside the saved HTML, no external image files required.
    Self-contained consulting client report rendered in a web portal: all embedded screenshots load from base64 data URIs inside the saved HTML, no external image files required.

    Refinement -- when not to use this

    Base64 inflates the bytes by roughly 33 percent: ten 500 KB screenshots become about 6.7 MB of HTML. A document with a handful of screenshots typically stays well under a couple of megabytes, comfortable for a SQL Server column and for page weight. A document with dozens of high-resolution images per page will hit size limits fast; in that case, keep the images as separate blobs and reassemble them at render time instead.

    The conversion is one-way at the markup level: after the rewrite, the original file paths are gone from the HTML, and editing an image means editing the embedded data URI, not the source file. If users need to re-author from originals, store the source files separately (for example keyed by a record ID) alongside the converted HTML. If the source images are disposable (screenshots taken once and never edited again), the one-way conversion is fine on its own.

    If the destination is an email message

    For email, use a different helper: GetEmailMessageWithLocalImagesEmbedded() produces a proper multipart/related MailMessage with CID-referenced linked resources, the format email clients expect. See Embedding Local Images for Email Clients. Using EmbedLocalImagesAsBase64() for an email body works in some clients but bloats the message by 33 percent and trips spam filters; the CID approach is the correct one for email.

    Decision guide for choosing between the EmbedLocalImagesAsBase64 helper (data URI embedding) and the GetEmailMessageWithLocalImagesEmbedded helper (CID multipart/related) in the SpiceLogic WinForms HTML Editor.
    Decision guide for choosing between the EmbedLocalImagesAsBase64 helper (data URI embedding) and the GetEmailMessageWithLocalImagesEmbedded helper (CID multipart/related) in the SpiceLogic WinForms HTML Editor.

    Last updated on May 15, 2026

    Put this into practice.

    .NET WinForms HTML Editor Control ships with free C# and VB.NET sample projects and a 14-day evaluation.

    Prefer a guided look? Book a free live demo with our engineers - live on Zoom or Teams, never a chatbot.