This page shows how to transfer files between a PC and a Yaskawa Motoman controller with the SDK: list, download, upload and delete jobs and data files, and download the CMOS backup. The file transfers use the UDP port 10041 of the High Speed Ethernet Server.

## List the files

`GetFileList(pattern)` lists the files whose name matches a pattern with `*`.

**C# : FileList**
```csharp
using UnderAutomation.Yaskawa;
using UnderAutomation.Yaskawa.HighSpeedEServer;

public class FileList
{
    static void Main()
    {
        var robot = new YaskawaRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Job files
        string[] jobs = robot.HighSpeedEServer.GetFileList("*.JBI").Files;

        // Variable data and condition files
        string[] dat = robot.HighSpeedEServer.GetFileList("*.DAT").Files;
        string[] cnd = robot.HighSpeedEServer.GetFileList("*.CND").Files;

        foreach (string file in jobs)
            Console.WriteLine(file);
        /**/

        robot.Disconnect();
    }
}
```

**Python : FileList**
```python
from underautomation.yaskawa.yaskawa_robot import YaskawaRobot
from underautomation.yaskawa.connect_parameters import ConnectParameters

robot = YaskawaRobot()
robot.connect(ConnectParameters("192.168.0.1"))

##
# Job files
jobs = robot.high_speed_e_server.get_file_list("*.JBI").files

# Variable data and condition files
dat = robot.high_speed_e_server.get_file_list("*.DAT").files
cnd = robot.high_speed_e_server.get_file_list("*.CND").files

for file in jobs:
    print(file)
##

robot.disconnect()
```

| Pattern | Files                                 |
| ------- | ------------------------------------- |
| `*.JBI` | Jobs                                  |
| `*.DAT` | Data files, for example the variables |
| `*.CND` | Condition files                       |
| `*.PRM` | Parameter files                       |

## Download a file

`GetFile(name)` downloads a file. `Content` is the text of the file, `ContentRaw` its bytes. The optional callback gives the progress of large files.

**C# : FileDownload**
```csharp
using UnderAutomation.Yaskawa;
using UnderAutomation.Yaskawa.HighSpeedEServer;

public class FileDownload
{
    static void Main()
    {
        var robot = new YaskawaRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Download a file, with an optional progress callback
        RobotFileContentData file = robot.HighSpeedEServer.GetFile("WELD01.JBI", progress =>
        {
            Console.WriteLine($"{progress.FileName}: {progress.DownloadedBytes} bytes");
        });

        // Text content, and the raw bytes for a binary file
        File.WriteAllText("WELD01.JBI", file.Content);
        File.WriteAllBytes("WELD01.copy.JBI", file.ContentRaw);
        /**/

        robot.Disconnect();
    }
}
```

**Python : FileDownload**
```python
from underautomation.yaskawa.yaskawa_robot import YaskawaRobot
from underautomation.yaskawa.connect_parameters import ConnectParameters

robot = YaskawaRobot()
robot.connect(ConnectParameters("192.168.0.1"))

##
# Download a file
file = robot.high_speed_e_server.get_file("WELD01.JBI")

# Text content, and the raw bytes for a binary file
with open("WELD01.JBI", "w", newline="") as f:
    f.write(file.content)

with open("WELD01.copy.JBI", "wb") as f:
    f.write(bytes(file.content_raw))
##

robot.disconnect()
```

## Upload a file

`LoadFile(name, content)` sends a text file to the controller. A job sent this way appears in the job list of the controller, ready to select.

**C# : FileUpload**
```csharp
using UnderAutomation.Yaskawa;
using UnderAutomation.Yaskawa.HighSpeedEServer;

public class FileUpload
{
    static void Main()
    {
        var robot = new YaskawaRobot();
        robot.Connect("192.168.0.1");

        /**/
        string content = File.ReadAllText("WELD01.JBI");

        // Send the file to the controller, with an optional progress callback
        robot.HighSpeedEServer.LoadFile("WELD01.JBI", content, progress =>
        {
            Console.WriteLine($"{progress.LoadedBytes} / {progress.TotalBytes} bytes");
        });
        /**/

        robot.Disconnect();
    }
}
```

**Python : FileUpload**
```python
from underautomation.yaskawa.yaskawa_robot import YaskawaRobot
from underautomation.yaskawa.connect_parameters import ConnectParameters

robot = YaskawaRobot()
robot.connect(ConnectParameters("192.168.0.1"))

##
with open("WELD01.JBI", newline="") as f:
    content = f.read()

# Send the file to the controller
robot.high_speed_e_server.load_file("WELD01.JBI", content)
##

robot.disconnect()
```

- To replace a file that exists on the controller, the parameters `RS029` and `RS214` must be `1`. See [Connect to your robot](/yaskawa/documentation/connect#allow_the_file_overwrite).
- The controller checks the syntax of a job when it receives it. A job with an error is refused, with the reason in the message of the `InvalidDataAnswerException`.

## Delete a file

`DeleteFile(name)` deletes a file of the controller. There is no undo: download the file first if you may need it.

**C# : FileDelete**
```csharp
using UnderAutomation.Yaskawa;
using UnderAutomation.Yaskawa.HighSpeedEServer;

public class FileDelete
{
    static void Main()
    {
        var robot = new YaskawaRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Delete a job file of the controller. There is no undo
        robot.HighSpeedEServer.DeleteFile("WELD01.JBI");
        /**/

        robot.Disconnect();
    }
}
```

**Python : FileDelete**
```python
from underautomation.yaskawa.yaskawa_robot import YaskawaRobot
from underautomation.yaskawa.connect_parameters import ConnectParameters

robot = YaskawaRobot()
robot.connect(ConnectParameters("192.168.0.1"))

##
# Delete a job file of the controller. There is no undo
robot.high_speed_e_server.delete_file("WELD01.JBI")
##

robot.disconnect()
```

## CMOS backup

`BatchDataBackup()` makes the controller write its CMOS backup (jobs, parameters, settings) to `/SPDRV/CMOSBK.BIN`. Then `GetFile` downloads it.

**C# : FileBackup**
```csharp
using UnderAutomation.Yaskawa;
using UnderAutomation.Yaskawa.HighSpeedEServer;

public class FileBackup
{
    static void Main()
    {
        var robot = new YaskawaRobot();
        robot.Connect("192.168.0.1");

        /**/
        // Ask the controller to write its CMOS backup to /SPDRV/CMOSBK.BIN.
        // It takes several seconds
        robot.HighSpeedEServer.BatchDataBackup();

        // Download the backup as binary
        RobotFileContentData backup = robot.HighSpeedEServer.GetFile("/SPDRV/CMOSBK.BIN");
        File.WriteAllBytes("CMOSBK.BIN", backup.ContentRaw);
        /**/

        robot.Disconnect();
    }
}
```

**Python : FileBackup**
```python
from underautomation.yaskawa.yaskawa_robot import YaskawaRobot
from underautomation.yaskawa.connect_parameters import ConnectParameters

robot = YaskawaRobot()
robot.connect(ConnectParameters("192.168.0.1"))

##
# Ask the controller to write its CMOS backup to /SPDRV/CMOSBK.BIN.
# It takes several seconds
robot.high_speed_e_server.batch_data_backup()

# Download the backup as binary
backup = robot.high_speed_e_server.get_file("/SPDRV/CMOSBK.BIN")
with open("CMOSBK.BIN", "wb") as f:
    f.write(bytes(backup.content_raw))
##

robot.disconnect()
```

- The backup takes several seconds. While it runs, a download of the file fails with an `InvalidDataAnswerException`: wait and try again.
- The command needs the automatic backup function with the RAM disk as device. In management mode, select `SETUP` > `AUTO BACKUP SET` and set `DEVICE` to `RAMDISK`. If this menu is missing, start the controller in maintenance mode and set `AUTOBACKUP` to `USED` in `SYSTEM` > `SETUP` > `OPTION FUNCTION`.

## Timeouts

The file transfers wait `FileTimeoutMilliseconds` (4000 ms by default) for each answer of the controller. Increase it if large files fail on a slow network. See [Connect to your robot](/yaskawa/documentation/connect#connection_parameters).

## Try it in the demo application

Everything on this page can be tried without writing code, in the **Files** page of the [demo application](/yaskawa/documentation/demo-app).

![Files page of the Yaskawa SDK demo application](/yaskawa/WinformsScreenshots/File.jpg)

Its C# source is [FileControl.cs](https://github.com/underautomation/Yaskawa.NET/blob/main/UnderAutomation.Yaskawa.Showcase.Forms/Components/FileControl.cs).

## Reference

**Methods of HighSpeedEServerClientBase**
```csharp
// Performs a backup of the robot's CMOS. The CMOS.BIN file is copied locally in the robot controller to "/SPDRC/CMOSBK.BIN". The operation can take several seconds to complete. After this command, the backup file can be downloaded using GetFile("/SPDRC/CMOSBK.BIN"). To enable this command : in "MANAGEMENT MODE", select {SETUP} - {AUTO BACKUP SET} and set "DEVICE" to "RAMDISK". If this menu is not available, Reboot the controller in Maintenance Mode and set System / Setup / OPTION FUNCTION / AUTOBACKUP to "Used", then do a "Safety board flash reset" from File / Initialize
RobotDataHeader BatchDataBackup(string file = "/SPDRV/CMOSBK.BIN");

// Deletes a file from the robot controller's file system. Use with caution as deleted files cannot be recovered.
RobotDataHeader DeleteFile(string name);

// Downloads (saves) a file from the robot controller to the PC. Large files are received in multiple blocks and automatically reassembled. Special use case : to download CMOS.BIN, first perform a CMOS backup using BatchDataBackup, then use GetFile with the backup file path.
RobotFileContentData GetFile(string name, HighSpeedEServerClientBase.GetFileProgressDelegate onGetFileProgress = null);

// Retrieves a list of files matching a pattern from the robot controller. Supports wildcards for matching multiple files.
RobotFileListData GetFileList(string pattern);

// Uploads (loads) a file from the PC to the robot controller. Large files are automatically split into 479-byte chunks for transmission.
RobotDataHeader[] LoadFile(string name, string content, HighSpeedEServerClientBase.LoadFileProgressDelegate onLoadFileProgress = null);
```

Every method also exists in an asynchronous version, with the same name followed by `Async` and an optional `CancellationToken`.

**Members of HighSpeedEServer.RobotFileListData**
```csharp
public class RobotFileListData : RobotData {
    // Gets the array of file names returned by the listing operation.
    // File names include extensions (e.g., "MYJOB.JBI", "SYSTEM.SYS").
    public string[] Files { get; }

    // Gets the list of response headers from multi-block transfers.
    // File listings may span multiple UDP packets for large directories.
    public List<RobotDataHeader> Headers { get; }
}
```

**Members of HighSpeedEServer.RobotFileContentData**
```csharp
public class RobotFileContentData : RobotData {
    // Gets the text content of the downloaded file.
    public string Content { get; }

    // Gets the text content of the downloaded file.
    public byte[] ContentRaw { get; }

    // Gets the name of the downloaded file.
    public string FileName { get; }

    public int GetParam(string section, int parameterLine, int parameterColumn)

    // Gets the list of response headers from multi-block transfers.
    // Large files are transferred in multiple UDP packets.
    public List<RobotDataHeader> Headers { get; }
}
```

**Members of HighSpeedEServer.LoadFileProgress**
```csharp
public class LoadFileProgress {
    // Gets whether the file upload has completed successfully.
    public bool Completed { get; }

    // Gets the name of the file being uploaded.
    public string FileName { get; }

    // Gets the number of bytes uploaded so far.
    public int LoadedBytes { get; }

    // Gets the total size of the file in bytes.
    public int TotalBytes { get; }
}
```

**Members of HighSpeedEServer.GetFileProgress**
```csharp
public class GetFileProgress {
    // Gets whether the file download has completed successfully.
    public bool Completed { get; }

    // Gets the number of bytes downloaded so far.
    public int DownloadedBytes { get; }

    // Gets the name of the file being downloaded.
    public string FileName { get; }
}
```