# Steps for IoT file download using Rest Client

**URL:** <https://community.criticalmanufacturing.com/t/steps-for-iot-file-download-using-rest-client/837>\
**Category:** Lounge\
**Created:** [September 9, 2026, 7:48am UTC](https://community.criticalmanufacturing.com/t/steps-for-iot-file-download-using-rest-client/837 "2026-09-09T07:48:20Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chang\_Lai](https://avatars.discourse-cdn.com/v4/letter/c/ee59a6/32.png) [@Chang\_Lai](https://community.criticalmanufacturing.com/u/Chang_Lai)\
**Post date:** [September 9, 2026, 7:48am UTC](https://community.criticalmanufacturing.com/t/steps-for-iot-file-download-using-rest-client/837/1 "2026-09-09T07:48:20Z")

</div>

Hello team,

I need some advice regarding IoT file download using Rest Client. Is it possible to download a file using OOB functionality of the Rest Client? They have exposed the file through GET - Serves files directly from a mounted directory over HTTP, so MES can retrieve a specific file by name without needing SFTP access.  
In order to simulate this for automation testing, what would need to be done in order to host a file with a mock Rest Server?

I came across the documentation for the Rest server([Rest Server - Critical Manufacturing Developer Portal](https://developer.criticalmanufacturing.com/11.3/explore/guides/customizations/automation/how-tos/test-orchestrator/plugins/simulators/RestServer/ "https://developer.criticalmanufacturing.com/11.3/explore/guides/customizations/automation/how-tos/test-orchestrator/plugins/simulators/restserver/")) and Mock MES instance([Connecting to a Live MES - Critical Manufacturing Developer Portal](https://developer.criticalmanufacturing.com/11.3/explore/guides/customizations/automation/how-tos/test-orchestrator/configuration/mes_instance/ "https://developer.criticalmanufacturing.com/11.3/explore/guides/customizations/automation/how-tos/test-orchestrator/configuration/mes\_instance/")) and received confirmation from CMGPT that setting this up is possible using the steps outlined below. I would like to kindly seek your confirmation if these steps are correct.

**Possible answer:**

- ✅ Yes, it is possible — the IoT Test Orchestrator’s Rest Server Simulator Plugin (`RestServer.PluginMain`) is the OOTB mechanism to host a mock HTTP server that serves files over GET for automation testing.
- ✅ The plugin is powered by WireMock, supports registering GET endpoints via `restSimulator.Register()`, and returns file content through a `SystemReply(200, fileContent)`.
- ✅ The mock server address/port is injected into the MES dataflow JSON so the REST Client driver targets it instead of the real external system.

**The Right Tool — Rest Server Simulator Plugin**

**A Simulator Plugin mirrors the implementation of its corresponding automation protocol. Since the MES uses a REST Client driver to retrieve files, a REST Client requires a REST Server simulator. The IoT Test Orchestrator Framework provides exactly this with the dedicated [Rest Server](https://developer.criticalmanufacturing.com/11.3/explore/guides/customizations/automation/how-tos/test-orchestrator/plugins/simulators/RestServer/ "https://developer.criticalmanufacturing.com/11.3/explore/guides/customizations/automation/how-tos/test-orchestrator/plugins/simulators/restserver/") simulator plugin**

**Steps:**

1. Add the Rest Server simulator plugin to the test scenario configuration
2. Register a GET endpoint that returns the file content as `SystemReply`
3. Read the file from disk in the test and return it in the handler
4. Configure the Rest Client driver in MES to point to the mock server address

## 📋 Step-by-Step Setup

### Step 1 — Add the Rest Server Plugin to the Scenario Configuration

To add the Rest Server simulator plugin to a test scenario, include its configuration in `ScenarioConfiguration`:

```auto
var port = new Random().Next(5000, 30000); // randomize to avoid concurrency collisions

var configuration = new ScenarioConfiguration()
    .ManagerId("Manager01")
    // ... other settings ...
    .AddSimulatorPlugin<RestServer.PluginMain>(new RestServer.Plugin.SettingsBuilder()
        .Address("http://localhost", port)
        .ServerSettings(new WireMock.Settings.WireMockServerSettings()
        {
            StartAdminInterface = true
        })
        .Build())
    .Build();

```

The Rest Server configuration properties are:

| Property | Type | Description | Default | |
| --- | --- | --- | --- | --- |
| `Address` | string | Address | — | |
| `Port` | int | Port | 8080 | |
| `WireMockServerSettings` | object | Server Settings | — | 3 |

* * *

### Step 2 — Register a GET Endpoint That Serves the File

Inside your test, retrieve the Rest Server simulator and register a GET endpoint that reads and returns the file content:

```auto
var restSimulator = (RestServer.PluginMain) context.Simulators["RestServer"];

// Read the file content from disk
var fileBytes = File.ReadAllBytes("path/to/your/testfile.csv");
var fileContent = Convert.ToBase64String(fileBytes); // or return as string if text

restSimulator.Register("/files/myfile.csv", (ISystemRequest request) =>
{
    // Return the file with HTTP 200 and appropriate content
    return new SystemReply(200, System.Text.Encoding.UTF8.GetString(fileBytes));

}, Common.Objects.Rest.RestVerb.Get);

```

The OOTB usage example for the Rest Server plugin shows registering a GET endpoint with `restSimulator.Register()`, providing the route, a handler lambda that returns a `SystemReply(statusCode, body)`, and the HTTP verb.

* * *

### Step 3 — Point the MES REST Client Driver to the Mock Server

In the Mock MES configuration, update the `restMasterDataPath` JSON to use the dynamically assigned port so the Rest Client driver targets the mock server address:

```auto
// Update the dataflow JSON to use the selected port
File.WriteAllText(
    restMasterDataPath,
    File.ReadAllText(restMasterDataPath).Replace("5000", port.ToString())
);

```

This ensures the **MES REST Client** in the workflow sends its `GET /files/myfile.csv` request to the mock server instead of the real external system.

* * *

### Step 4 — Verify the File Was Requested

```auto
var fileWasRequested = false;

restSimulator.Register("/files/myfile.csv", (ISystemRequest request) =>
{
    fileWasRequested = true;
    var fileBytes = File.ReadAllBytes("path/to/testfile.csv");
    return new SystemReply(200, System.Text.Encoding.UTF8.GetString(fileBytes));
}, Common.Objects.Rest.RestVerb.Get);

// ... trigger the MES workflow ...

scenario.Utilities.WaitFor(50, "File was never requested", () => fileWasRequested);

```

Thank You.

---

<div class="post-metadata">

**Author:** ![Joao\_Roque](https://yyz2.discourse-cdn.com/flex050/user_avatar/community.criticalmanufacturing.com/joao_roque/32/24_2.png) [@Joao\_Roque](https://community.criticalmanufacturing.com/u/Joao_Roque)\
**Post date:** [September 9, 2026, 7:50am UTC](https://community.criticalmanufacturing.com/t/steps-for-iot-file-download-using-rest-client/837/2 "2026-09-09T07:50:20Z")

</div>

Hi,  
For testing the test orchestrator docs are here [Rest Client - Critical Manufacturing Developer Portal](https://developer.criticalmanufacturing.com/explore/guides/customizations/automation/how-tos/test-orchestrator/plugins/simulators/RestClient/ "https://developer.criticalmanufacturing.com/explore/guides/customizations/automation/how-tos/test-orchestrator/plugins/simulators/restclient/"). I would point out that for large files you probably need an http stream which I think it’s not supported in the Rest Client or Rest Server.

---

<div class="post-metadata">

**Author:** ![Joao\_Moreira](https://avatars.discourse-cdn.com/v4/letter/j/b9bd4f/32.png) [@Joao\_Moreira](https://community.criticalmanufacturing.com/u/Joao_Moreira)\
**Post date:** [September 9, 2026, 4:49pm UTC](https://community.criticalmanufacturing.com/t/steps-for-iot-file-download-using-rest-client/837/3 "2026-09-09T16:49:00Z")

</div>

Hi,

Yes, as João Roque said, the Rest Client driver cannot retrieve a raw binary response, such as `application/pdf`, `image/png`, or `application/octet-stream`. As workarround, you could use an endpoint that returns the file as text, or one that returns it Base64-encoded inside a JSON response.

Below, I describe how you could configure both these scenarios:

### Scenario 1: Downloading a Text/XML File

The rest client driver never writes to disk. It returns the content into the workflow, and a **File** driver command writes it. A download is therefore two commands: one on the REST Client protocol to fetch the content, and one on the File protocol to write it.

For a text response, such as the one below, the content arrives as a String.

```json
{
    "Name": "DownloadReport",
    "Description": "Retrieve the daily report as CSV",
    "DeviceCommandId": "/reports/:reportId",
    "ExtendedData": {
        "requestMethod": "GET",
        "timeout": 60000,
        "successfulStatusCodes": "200"
    },
    "Parameters": [
        {
            "Name": "reportId",
            "DataType": "String",
            "AutomationProtocolDataType": "String",
            "ExtendedData": {
                "operationParameters": "PathParameter"
            },
            "IsMandatory": true
        }
    ]
}

```

In the workflow, should connect the output of the **Execute Equipment Command** task that runs this command to the `content` parameter of a `CreateFile` command on the File driver:

```json
{
    "Name": "WriteReport",
    "Description": "Write the retrieved report to disk",
    "DeviceCommandId": "WriteReport",
    "ExtendedData": {
        "commandType": "CreateFile"
    },
    "Parameters": [
        { "Name": "path", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true },
        { "Name": "content", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true }
    ]
}

```

#### Scenario 2: Binary File Through a Base64 Response

Many document APIs return a binary file as a Base64 string inside a JSON object, for example:

```json
{
    "fileName": "certificate-4471.pdf",
    "content": "JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGgg..."
}

```

The driver parses that response as JSON and returns it as an Object. Extract `fileName` and `content` with a converter, then write the file with a `CreateFile` command whose `encoding` parameter is set to `base64`, which decodes the string back to the original bytes:

```json
{
    "Name": "WriteCertificate",
    "Description": "Write a Base64 payload to disk as a binary file",
    "DeviceCommandId": "WriteCertificate",
    "ExtendedData": {
        "commandType": "CreateFile"
    },
    "Parameters": [
        { "Name": "path", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true },
        { "Name": "content", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true },
        { "Name": "encoding", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": false }
    ]
}

```

Set `encoding` to `base64` when the command is executed. Leaving it at the default of `utf-8` writes the Base64 text itself rather than the decoded file.

---

<div class="post-metadata">

**Author:** ![Joao\_Roque](https://yyz2.discourse-cdn.com/flex050/user_avatar/community.criticalmanufacturing.com/joao_roque/32/24_2.png) [@Joao\_Roque](https://community.criticalmanufacturing.com/u/Joao_Roque)\
**Post date:** [September 10, 2026, 9:41am UTC](https://community.criticalmanufacturing.com/t/steps-for-iot-file-download-using-rest-client/837/4 "2026-09-10T09:41:13Z")

</div>

As a side note this is also common in OPC-UA. In that protocol we do support having retrieving files from OPC-UA and then writing them somewhere or sending them to the MES [Read File - Critical Manufacturing Documentation Portal](https://help.criticalmanufacturing.com/userguide/automation/reference/tasks/opcua/task_readfile/?h=opc)

---

<div class="post-metadata">

**Author:** ![system](https://yyz2.discourse-cdn.com/flex050/user_avatar/community.criticalmanufacturing.com/system/32/23_2.png) [@system](https://community.criticalmanufacturing.com/u/system)\
**Post date:** [September 12, 2026, 9:41am UTC](https://community.criticalmanufacturing.com/t/steps-for-iot-file-download-using-rest-client/837/5 "2026-09-12T09:41:26Z")

</div>

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.
