Integration

How to save rich text with images that survive a reload

Connect image uploads, document saving and persistent storage. Handle slow uploads, failed saves and private image URLs without losing the draft.

5 min read

An image can look correct in an editor and still disappear when the document is opened tomorrow. The preview, the uploaded file and the saved HTML are three different things. A reliable save flow has to connect all three.

1. Give the image a durable home

Store the file in persistent storage and put its URL in the document. Keep a browser-only blob: URL out of persisted content. Base64 embeds the bytes in the HTML, which can be useful for small self-contained content but makes larger documents expensive to transfer and store. Choose this deliberately rather than treating it as an upload fallback.

For RichTextEditor, start with storing images as files and the upload integration reference. The server implementation depends on your application: ASP.NET Core, ASP.NET or PHP.

2. Finish uploads before reading the final HTML

Uploading and saving are asynchronous operations. If Save reads HTML while a picture is still uploading, it can capture a temporary source. Track active uploads in your integration, show their state beside Save, and read the editor content only when uploads have finished successfully. Prevent another submission while the save itself is in progress.

This is an integration sequence, not a new editor API:

  1. Wait until your upload integration reports no active uploads.
  2. If an upload failed, show a recovery action and let the user retry or remove the image.
  3. Read the current editor HTML, then submit it with the document identifier and revision.
  4. Validate and store it on the server; show Saved only after the server confirms success.

The custom upload handler example includes application-owned pending and error tracking. That state belongs to the example integration; do not assume every editor instance exposes it automatically.

3. Keep validation on the server

Client checks improve feedback but cannot authorize a request. Validate uploads and the document save independently. Apply your HTML sanitization policy, check permitted image URLs and associate stored assets with the correct user or tenant. Never accept a client-supplied disk path as permission to read or delete a file.

A signed image URL can expire while the document remains valid. For private assets, design authorized delivery or resolve stable asset identifiers when rendering. Do not make private images public just to avoid an expired-link problem.

4. Treat failed saves as recoverable

An upload may succeed while saving the document fails. Keep the draft available, explain which operation failed, and allow a retry. Use a revision check to avoid silently overwriting another person’s changes. If retries can create records twice, give the save endpoint an application-level idempotency strategy.

Removing an image from one document does not prove the file is unused. It may appear in another document or a retained revision. Clean up abandoned uploads with an ownership-aware retention process rather than deleting every image missing from the current HTML.

5. Test the whole round trip

Use the image upload troubleshooting guide when one of these checks fails. For the document storage format itself, see how to store rich text.

How other editors approach upload completion

TinyMCE documents explicit image-upload completion before submission. CKEditor exposes pending actions for long-running work. Their APIs differ, but the application requirement is the same: a visible preview is not proof that the document is ready to persist.


RichTextEditor is a perpetual-licence JavaScript editor — one purchase, self-hosted, no metered editor loads. Download the evaluation or see how it compares.