# Loading and Saving Documents

> Load documents into the Document Editor and save them: LoadText in the view, loadDocument and saveDocument in JavaScript, a controller that stores DOCX files.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > Document Editor > Loading and Saving Documents
- **4033 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/load-save/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/load-save/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/load-save/llms-full.txt

---

With the editor added to an application, as in [ASP.NET Core](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-editor/aspnet-core/llms-full.txt) in Getting Started, the next step is to open and store real documents. They get into the Document Editor when the view is rendered or from JavaScript while the editor is open, and back to your server through an ASP.NET Core controller that stores them.

The examples extend the ASP.NET Core MVC application of that tutorial. The same JavaScript calls work in the Angular, React and JavaScript frontends.

### How Loading and Saving Works

While a document is open in the editor, it exists in the editing session on the server, not as a file. You decide where it comes from and where it goes:

- **When the view is rendered**, your Razor view passes a document to the editor with `LoadText`. The document can be a file on the server, a byte array or a string.
- **While the editor is open**, JavaScript in the browser replaces the document with `loadDocument` and gets the current document with `saveDocument`. Both exchange the document as data, which your code sends to or receives from your server.
- **In Blazor**, your C# code calls `LoadDocumentAsync` and `SaveDocumentAsync` of the component instead; see [Blazor](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-editor/blazor/llms-full.txt) in Getting Started.

The editor has no storage of its own. Nothing is saved until your code saves it.

### Load a Document When the View Is Rendered

[LoadText](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web-mvc/textcontrol/loadtext-method/llms-full.txt) replaces the content of the editor before the view is sent to the browser. It has one overload for each kind of source:

| Overload | Loads |
|---|---|
| `LoadText(string path, StreamType)` | A file on the server |
| `LoadText(System.IO.FileStream, StreamType)` | A stream, from its current position |
| `LoadText(byte[] data, BinaryStreamType)` | A document in a byte array, for example from a database |
| `LoadText(string data, StringStreamType)` | A document in a string, for example HTML |

The format parameters are the [StreamType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/streamtype/enumeration/llms-full.txt), [BinaryStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/binarystreamtype/enumeration/llms-full.txt) and [StringStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/stringstreamtype/enumeration/llms-full.txt) enumerations of the `TXTextControl.Web` namespace. The tutorial already loads a file and an HTML string. To load a document that your controller reads, for example from a database, pass it as a byte array. In *Controllers/HomeController.cs*, read the document in the `Index` action:

```csharp
public IActionResult Index()
{
    // Read the document, for example from a database or a file
    ViewBag.Document = System.IO.File.ReadAllBytes("Documents/template.docx");

    return View();
}
```

Then pass the byte array to `LoadText` in *Views/Home/Index.cshtml*:

```cshtml
@using TXTextControl.Web.MVC

@Html.TXTextControl().TextControl().LoadText(
    (byte[])ViewBag.Document,
    TXTextControl.Web.BinaryStreamType.WordprocessingML).Render()
```

`WordprocessingML` is the DOCX format. When the page opens, the editor shows the document.

### Load a Document From JavaScript

[TXTextControl.loadDocument](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol/loaddocument-method/llms-full.txt) replaces the document in the editor while it is open. It takes the format, the document as a base64-encoded string, and a callback that is called when loading is finished:

```javascript
function loadHtml() {
  var html = "<p>Dear customer,</p><p>thank you for your order.</p>";

  TXTextControl.loadDocument(
    TXTextControl.StreamType.HTMLFormat,
    TXTextControl.btoaUTF8(html),
    function (result) {
      console.log(result.bytesRead + " bytes loaded");
    });
}
```

- The first parameter is a value of the [TXTextControl.StreamType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol/streamtype-enumeration/llms-full.txt) enumeration of the JavaScript API.
- [btoaUTF8](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol/btoautf8-method/llms-full.txt) encodes a string as base64. Unlike the browser's `btoa`, it handles all Unicode characters.
- The callback receives a [LoadDocumentCallbackData](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/loaddocumentcallbackdata/llms-full.txt) object with information about the loaded document, such as [bytesRead](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/loaddocumentcallbackdata/bytesread-property/llms-full.txt).

An optional fourth parameter takes a [LoadSettings](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol-loadsettings/llms-full.txt) object with settings such as the password of a protected document ([userPassword](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol-loadsettings/userpassword-property/llms-full.txt)) or whether images are loaded ([loadImages](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol-loadsettings/loadimages-property/llms-full.txt)). The optional fifth parameter is an error callback.

Call `loadDocument` only after the editor has raised the `textControlLoaded` event, for example from a button or inside a handler of this event. After a document has been loaded, the editor raises the `documentLoaded` event; see [Events](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/events/llms-full.txt).

### Save a Document From JavaScript

[TXTextControl.saveDocument](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol/savedocument-method/llms-full.txt) saves the current document in a format and passes the result to a callback:

```javascript
function saveAsDocx() {
  TXTextControl.saveDocument(TXTextControl.StreamType.WordprocessingML, function (result) {
    console.log(result.bytesWritten + " bytes written");
  });
}
```

The callback receives a [SaveDocumentResult](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/savedocumentresult/llms-full.txt). Its [data](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/savedocumentresult/data-property/llms-full.txt) property depends on the format:

| Format | `data` contains |
|---|---|
| Binary formats such as DOCX, PDF and the TX Text Control format | The document as a base64-encoded string |
| Text formats such as HTML and RTF | The document as plain text |

Keep this in mind when you send the result to your server: decode base64 only for binary formats. An optional third parameter takes a [SaveSettings](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol-savesettings/llms-full.txt) object with settings such as the document title ([documentTitle](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol-savesettings/documenttitle-property/llms-full.txt)) or a password for a PDF document ([userPassword](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol-savesettings/userpassword-property/llms-full.txt)).

### Store Documents on the Server

In most applications, users open a stored document, edit it and save it back. The following example stores DOCX documents in the *Documents* folder of the project. A controller receives the documents that `saveDocument` creates and returns documents for `loadDocument`.

#### Add the Controller

Create *Controllers/DocumentController.cs* with the following code:

```csharp
using Microsoft.AspNetCore.Mvc;

public class DocumentController : Controller
{
    // Return a document from the Documents folder as base64-encoded data
    [HttpGet]
    public DocumentData Load(string name)
    {
        var file = Path.Combine("Documents", Path.GetFileName(name));

        return new DocumentData
        {
            Name = name,
            Data = Convert.ToBase64String(System.IO.File.ReadAllBytes(file))
        };
    }

    // Store a document that saveDocument created in a binary format
    [HttpPost]
    public bool Save([FromBody] DocumentData documentData)
    {
        var file = Path.Combine("Documents", Path.GetFileName(documentData.Name));
        System.IO.File.WriteAllBytes(file, Convert.FromBase64String(documentData.Data));

        return true;
    }
}

public class DocumentData
{
    public string Name { get; set; } = string.Empty;
    public string Data { get; set; } = string.Empty;
}
```

The code works as follows:

- `Load` reads a file and returns it as a JSON object with the name and the base64-encoded data.
- `Save` receives the same JSON object in the body of a POST request, decodes the data and writes the file.
- `Path.GetFileName` keeps only the file name of the name the browser sends, so that a request can't write outside the *Documents* folder.

The controller expects binary data. To store HTML or RTF, which `saveDocument` returns as plain text, write the text instead of decoding it.

#### Add the Buttons

Replace the content of *Views/Home/Index.cshtml* with the following code:

```cshtml
@using TXTextControl.Web.MVC

@Html.TXTextControl().TextControl().LoadText(
    "Documents/template.docx",
    TXTextControl.Web.StreamType.WordprocessingML).Render()

<input type="button" onclick="saveToServer()" value="Save Document" />
<input type="button" onclick="loadFromServer()" value="Load Document" />

<script>
    function saveToServer() {
        TXTextControl.saveDocument(TXTextControl.StreamType.WordprocessingML, function (result) {
            fetch("/Document/Save", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ name: "output.docx", data: result.data })
            });
        });
    }

    function loadFromServer() {
        fetch("/Document/Load?name=output.docx")
            .then(response => response.json())
            .then(stored => {
                TXTextControl.loadDocument(
                    TXTextControl.StreamType.WordprocessingML,
                    stored.data,
                    function (result) {
                        console.log(result.bytesRead + " bytes loaded");
                    });
            });
    }
</script>
```

What the page does:

- `LoadText` opens *Documents/template.docx* when the page is rendered, as in the tutorial.
- `saveToServer` saves the document as DOCX and posts the base64-encoded data to the `Save` action.
- `loadFromServer` requests *output.docx* from the `Load` action and passes the data to `loadDocument`.

Run the application, change the document and click **Save Document**. The project's *Documents* folder now contains *output.docx*. Change the document again and click **Load Document** to return to the saved version.

### Append a Document

[TXTextControl.append](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol/append-method/llms-full.txt) adds a document to the end of the current document instead of replacing it:

```javascript
function appendParagraph() {
  TXTextControl.append(
    TXTextControl.StreamType.HTMLFormat,
    TXTextControl.btoaUTF8("<p>Appended text</p>"),
    function (result) {
      console.log(result.bytesRead + " bytes appended");
    },
    null,
    TXTextControl.AppendSettings.StartWithNewParagraph);
}
```

The fourth parameter is a `LoadSettings` object, which can be `null`. The fifth is a value of [AppendSettings](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol/appendsettings-enumeration/llms-full.txt): `None` inserts the text at the end of the last paragraph, `StartWithNewParagraph` in a new paragraph and `StartWithNewSection` in a new section.

### Angular and React

The Angular and React components have no property that loads a document. Load and save with the same JavaScript API once the editor is ready: in Angular, in a handler of the `txDocumentEditorLoaded` event, and in React, in the function of the `onLoad` property. [Angular](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-editor/angular/llms-full.txt) and [React](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-editor/react/llms-full.txt) in Getting Started show where this code goes.

### Formats

The JavaScript `StreamType` enumeration contains the formats `WordprocessingML` (DOCX), `RichTextFormat` (RTF), `HTMLFormat`, `PlainText`, `InternalUnicodeFormat` (the TX Text Control format), `AdobePDF`, `SpreadsheetML` (XLSX) and `MSWord` (DOC).

The Document Editor backend uses the Core engine, which doesn't load or save DOC documents. RTF is supported by the Core engine since version 34.0. [Supported File Formats](https://docs.textcontrol.com/tx-text-control-dotnet-server/overview/file-formats/llms-full.txt) lists the formats and their limitations.

### Next Steps

- [Events](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/events/llms-full.txt): react when a document has been loaded.
- [JavaScript API](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/javascript-api/llms-full.txt): the callbacks and objects of the API used on this page.
- [Architecture](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/architecture/llms-full.txt): where the document lives while it is open.
- [Saving and Converting Documents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/saving-converting/llms-full.txt): process stored documents on the server with `ServerTextControl`.

---

## Nearby

- **Previous:** [Architecture](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/architecture/llms-full.txt)
- **Next:** [Document Properties](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/properties/llms-full.txt)
