SFTP (SSH File Transfer Protocol) gives access to the files of a Universal Robots controller: download, upload, list, rename and delete programs, installations and any other file. This page shows how to connect and use the SFTP client of the SDK. The controller runs Linux: the same connection can also run commands, see [SSH](/universal-robots/documentation/ssh-commands).

## Prerequisites

- Secure Shell is enabled on the robot. On PolyScope, open `Settings`, `Security`, `Secure Shell`.
- The Linux user and its password. The SDK uses `ur` and `easybot` by default.

| Target    | User   | Password  | Folder of the programs           |
| --------- | ------ | --------- | -------------------------------- |
| Robot     | `root` | `easybot` | `/programs`                      |
| URSim     | `ur`   | `easybot` | `/home/ur/ursim-current/programs` |

Change the default password of the robot: anyone on the network who knows it can change its files.

## Example

SFTP is disabled by default: set `Ssh.EnableSftp` in `ConnectParameters`.

**C# : Sftp**
```csharp
using UnderAutomation.UniversalRobots;
using UnderAutomation.UniversalRobots.Ssh.Tools.Sftp;

class Sftp
{
  static void Main(string[] args)
  {
    /**/
    var robot = new UR();

    var parameters = new ConnectParameters("192.168.0.1");

    // SFTP is disabled by default
    parameters.Ssh.EnableSftp = true;

    // "ur" and "easybot" by default
    parameters.Ssh.Username = "root";
    parameters.Ssh.Password = "easybot";

    robot.Connect(parameters);

    // Download a program from the robot
    robot.Sftp.DownloadFile("/programs/my_program.urp", @"C:\temp\my_program.urp");

    // Send a program to the robot
    robot.Sftp.UploadFile(@"C:\temp\my_program.urp", "/programs/my_program.urp");

    // Rename, check, delete
    robot.Sftp.RenameFile("/programs/my_program.urp", "/programs/old_program.urp");
    bool exists = robot.Sftp.Exists("/programs/old_program.urp");
    robot.Sftp.DeleteFile("/programs/old_program.urp");

    // List a folder
    foreach (SftpFile item in robot.Sftp.ListDirectory("/programs/"))
      Console.WriteLine(item.Name + " " + item.IsDirectory + " " + item.Length + " " + item.LastWriteTimeUtc);

    // Read and write text files
    robot.Sftp.WriteAllText("/programs/note.txt", "Hello");
    string text = robot.Sftp.ReadAllText("/programs/note.txt");
    /**/
  }
}
```

**Python : Sftp**
```python
from underautomation.universal_robots.ur import UR
from underautomation.universal_robots.connect_parameters import ConnectParameters

##
robot = UR()

parameters = ConnectParameters("192.168.0.1")

# SFTP is disabled by default
parameters.ssh.enable_sftp = True

# "ur" and "easybot" by default
parameters.ssh.username = "root"
parameters.ssh.password = "easybot"

robot.connect(parameters)

# Download a program from the robot
robot.sftp.download_file("/programs/my_program.urp", "C:\\temp\\my_program.urp")

# Send a program to the robot, with the number of bytes sent
robot.sftp.upload_file("C:\\temp\\my_program.urp", "/programs/my_program.urp",
                       lambda sent: print(f"{sent} bytes sent"))

# Rename, check, delete
robot.sftp.rename_file("/programs/my_program.urp", "/programs/old_program.urp")
exists = robot.sftp.exists("/programs/old_program.urp")
robot.sftp.delete_file("/programs/old_program.urp")

# List a folder
for item in robot.sftp.list_directory("/programs/"):
    print(item.name, item.is_directory, item.length, item.last_write_time_utc)

# Read and write text files
robot.sftp.write_all_text("/programs/note.txt", "Hello")
text = robot.sftp.read_all_text("/programs/note.txt")
##
```

The progress callbacks of `DownloadFile`, `UploadFile` and `ListDirectory` are optional. In Python, pass a function that takes the number of bytes or of entries.

## List the programs

`EnumeratePrograms` and `EnumerateInstallations` return the relative paths of the `.urp` and `.installation` files of the programs folder and of its subfolders. They look in `/programs`, or in the folder of URSim when `/programs` does not exist. The client also works without `UR`:

**C# : SftpDirect**
```csharp
using UnderAutomation.UniversalRobots.Ssh;

class SftpDirect
{
  static void Main(string[] args)
  {
    /**/
    // An SFTP client, without a UR instance
    var client = new SftpClient();

    client.Connect("192.168.0.1", "root", "easybot");

    // Relative paths of the .urp files of the programs folder, and of its subfolders
    string[] programs = client.EnumeratePrograms();
    string[] installations = client.EnumerateInstallations();

    client.Disconnect();
    /**/
  }
}
```

**Python : SftpDirect**
```python
from underautomation.universal_robots.ssh.sftp_client import SftpClient

##
# An SFTP client, without a UR instance
client = SftpClient()

client.connect("192.168.0.1", "root", "easybot")

# Relative paths of the .urp files of the programs folder, and of its subfolders
programs = client.enumerate_programs()
installations = client.enumerate_installations()

client.disconnect()
##
```

## Operations

| Task                      | Methods                                                         |
| ------------------------- | --------------------------------------------------------------- |
| Transfer a file           | `DownloadFile`, `UploadFile`, with a local path or a `Stream`   |
| Read and write a file     | `ReadAllText`, `ReadAllLines`, `ReadAllBytes`, `WriteAllText`, `WriteAllLines`, `WriteAllBytes`, `AppendAllText`, `OpenRead`, `OpenWrite` |
| Browse                    | `ListDirectory`, `Exists`, `Get`, `GetAttributes`, `ChangeDirectory`, `WorkingDirectory` |
| Change                    | `CreateDirectory`, `RenameFile`, `DeleteFile`, `DeleteDirectory`, `Delete`, `ChangePermissions` |
| Dates                     | `GetLastWriteTime`, `GetLastAccessTime`, and their UTC versions |

A program sent with SFTP is loaded with the Dashboard Server (`LoadProgram`) or the REST API. See [Transfer files and backups](/universal-robots/documentation/how-to-transfer-files).

## Try it in the demo application

Everything on this page can be tried without writing code, in the **File handling (SFTP)** page of the [demo application](/universal-robots/documentation/demo-app).

![File handling (SFTP) page of the Universal Robots SDK demo application](/universal-robots/WinformsScreenshots/Sftp.jpg)

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

## Reference

**Members of Ssh.SftpClient**
```csharp
public class SftpClient : SftpClientBase {
    public SftpClient()

    // Connects to the robot
    public void Connect(string ip, string username, string password, int port = 22)
}
```

**Members of Ssh.Internal.SftpClientBase**
```csharp
public abstract class SftpClientBase : URServiceBase {
    protected SftpClientBase()

    // Appends lines to a file, creating the file if it does not already exist.
    public void AppendAllLines(string path, string[] contents)

    // Appends lines to a file by using a specified encoding, creating the file if it does not already exist.
    public void AppendAllLines(string path, string[] contents, Encoding encoding)

    // Appends the specified string to the file, creating the file if it does not already exist.
    public void AppendAllText(string path, string contents)

    // Appends the specified string to the file, creating the file if it does not already exist.
    public void AppendAllText(string path, string contents, Encoding encoding)

    // Creates a <xref href="System.IO.StreamWriter" data-throw-if-not-resolved="false"></xref> that appends UTF-8 encoded text to the specified file,
    // creating the file if it does not already exist.
    public StreamWriter AppendText(string path)

    // Creates a <xref href="System.IO.StreamWriter" data-throw-if-not-resolved="false"></xref> that appends text to a file using the specified
    // encoding, creating the file if it does not already exist.
    public StreamWriter AppendText(string path, Encoding encoding)

    // Begins an asynchronous file downloading into the stream.
    public IAsyncResult BeginDownloadFile(string path, Stream output)

    // Begins an asynchronous file downloading into the stream.
    public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback)

    // Begins an asynchronous file downloading into the stream.
    public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback, object state, Action<ulong> downloadCallback = null)

    // Begins an asynchronous operation of retrieving list of files in remote directory.
    public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, object state, Action<int> listCallback = null)

    // Begins the synchronize directories.
    public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback asyncCallback, object state)

    // Begins an asynchronous uploading the stream into remote file.
    public IAsyncResult BeginUploadFile(Stream input, string path)

    // Begins an asynchronous uploading the stream into remote file.
    public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback)

    // Begins an asynchronous uploading the stream into remote file.
    public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback, object state, Action<ulong> uploadCallback = null)

    // Begins an asynchronous uploading the stream into remote file.
    public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback asyncCallback, object state, Action<ulong> uploadCallback = null)

    // Gets or sets the maximum size of the buffer in bytes.
    public uint BufferSize { get; set; }

    // Changes remote directory to path.
    public void ChangeDirectory(string path)

    // Changes permissions of file(s) to specified mode.
    public void ChangePermissions(string path, short mode)

    // Connects to the robot's SFTP server.
    protected void ConnectInternal(string ip, int port, string username, string password)

    // Gets a value indicating if this client is connected to the robot
    public bool Connected { get; }

    // Creates or overwrites a file in the specified path.
    public SftpFileStream Create(string path)

    // Creates or overwrites the specified file.
    public SftpFileStream Create(string path, int bufferSize)

    // Creates remote directory specified by path.
    public void CreateDirectory(string path)

    // Creates or opens a file for writing UTF-8 encoded text.
    public StreamWriter CreateText(string path)

    // Creates or opens a file for writing text using the specified encoding.
    public StreamWriter CreateText(string path, Encoding encoding)

    // Deletes the specified file or directory.
    public void Delete(string path)

    // Deletes remote directory specified by path.
    public void DeleteDirectory(string path)

    // Deletes remote file specified by path.
    public void DeleteFile(string path)

    // Disconnects this client from the SFTP server.
    public void Disconnect()

    // Downloads remote file specified by the path into the stream.
    public void DownloadFile(string path, Stream output, Action<ulong> downloadCallback = null)

    // Downloads remote file specified by the path into the stream.
    public void DownloadFile(string path, string localPath, Action<ulong> downloadCallback = null)

    // Ends an asynchronous file downloading into the stream.
    public void EndDownloadFile(IAsyncResult asyncResult)

    // Ends an asynchronous operation of retrieving list of files in remote directory.
    public SftpFile[] EndListDirectory(IAsyncResult asyncResult)

    // Ends the synchronize directories.
    public FileInfo[] EndSynchronizeDirectories(IAsyncResult asyncResult)

    // Ends an asynchronous uploading the stream into remote file.
    public void EndUploadFile(IAsyncResult asyncResult)

    // Enumerates installations with .installation extension. It searches recursively installations in "/programs" if it exists, or "/home/ur/ursim-current/programs" for simulator
    public string[] EnumerateInstallations()

    // Enumerates programs with .urp extension. It searches recursively programs in "/programs" if it exists, or "/home/ur/ursim-current/programs" for simulator
    public string[] EnumeratePrograms()

    // Checks whether file or directory exists;
    public bool Exists(string path)

    // Gets reference to remote file or directory.
    public SftpFile Get(string path)

    // Gets the <xref href="UnderAutomation.UniversalRobots.Ssh.Tools.Sftp.SftpFileAttributes" data-throw-if-not-resolved="false"></xref> of the file on the path.
    public SftpFileAttributes GetAttributes(string path)

    // Returns the date and time the specified file or directory was last accessed.
    public DateTime GetLastAccessTime(string path)

    // Returns the date and time, in coordinated universal time (UTC), that the specified file or directory was last accessed.
    public DateTime GetLastAccessTimeUtc(string path)

    // Returns the date and time the specified file or directory was last written to.
    public DateTime GetLastWriteTime(string path)

    // Returns the date and time, in coordinated universal time (UTC), that the specified file or directory was last written to.
    public DateTime GetLastWriteTimeUtc(string path)

    // Gets status using statvfs@openssh.com request.
    public SftpFileSytemInformation GetStatus(string path)

    // Retrieves list of files in remote directory.
    public SftpFile[] ListDirectory(string path, Action<int> listCallback = null)

    // Opens a <xref href="UnderAutomation.UniversalRobots.Ssh.Tools.Sftp.SftpFileStream" data-throw-if-not-resolved="false"></xref> on the specified path with read/write access.
    public SftpFileStream Open(string path, FileMode mode)

    // Opens a <xref href="UnderAutomation.UniversalRobots.Ssh.Tools.Sftp.SftpFileStream" data-throw-if-not-resolved="false"></xref> on the specified path, with the specified mode and access.
    public SftpFileStream Open(string path, FileMode mode, FileAccess access)

    // Opens an existing file for reading.
    public SftpFileStream OpenRead(string path)

    // Opens an existing UTF-8 encoded text file for reading.
    public StreamReader OpenText(string path)

    // Opens a file for writing.
    public SftpFileStream OpenWrite(string path)

    // Gets or sets the operation timeout.
    public TimeSpan OperationTimeout { get; set; }

    // Gets sftp protocol version.
    public int ProtocolVersion { get; }

    // Opens a binary file, reads the contents of the file into a byte array, and closes the file.
    public byte[] ReadAllBytes(string path)

    // Opens a text file, reads all lines of the file using UTF-8 encoding, and closes the file.
    public string[] ReadAllLines(string path)

    // Opens a file, reads all lines of the file with the specified encoding, and closes the file.
    public string[] ReadAllLines(string path, Encoding encoding)

    // Opens a text file, reads all lines of the file with the UTF-8 encoding, and closes the file.
    public string ReadAllText(string path)

    // Opens a file, reads all lines of the file with the specified encoding, and closes the file.
    public string ReadAllText(string path, Encoding encoding)

    // Reads the lines of a file with the UTF-8 encoding.
    public string[] ReadLines(string path)

    // Read the lines of a file that has a specified encoding.
    public string[] ReadLines(string path, Encoding encoding)

    // Renames remote file from old path to new path.
    public void RenameFile(string oldPath, string newPath)

    // Renames remote file from old path to new path.
    public void RenameFile(string oldPath, string newPath, bool isPosix)

    // Sets the specified <xref href="UnderAutomation.UniversalRobots.Ssh.Tools.Sftp.SftpFileAttributes" data-throw-if-not-resolved="false"></xref> of the file on the specified path.
    public void SetAttributes(string path, SftpFileAttributes fileAttributes)

    // Creates a symbolic link from old path to new path.
    public void SymbolicLink(string path, string linkPath)

    // Synchronizes the directories.
    public FileInfo[] SynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern)

    // Uploads stream into remote file.
    public void UploadFile(Stream input, string path, Action<ulong> uploadCallback = null)

    // Uploads stream into remote file.
    public void UploadFile(Stream input, string path, bool canOverride, Action<ulong> uploadCallback = null)

    // Uploads file into remote file.
    public void UploadFile(string localPath, string path, Action<ulong> uploadCallback = null)

    // Gets remote working directory.
    public string WorkingDirectory { get; }

    // Writes the specified byte array to the specified file, and closes the file.
    public void WriteAllBytes(string path, byte[] bytes)

    // Writes a collection of strings to the file using the UTF-8 encoding, and closes the file.
    public void WriteAllLines(string path, string[] contents)

    // Writes the specified string to the file using the UTF-8 encoding, and closes the file.
    public void WriteAllText(string path, string contents)

    // Writes the specified string to the file using the specified encoding, and closes the file.
    public void WriteAllText(string path, string contents, Encoding encoding)
}
```

**Members of Ssh.Tools.Sftp.SftpFile**
```csharp
public class SftpFile {
    // Gets the file attributes.
    public SftpFileAttributes Attributes { get; }

    // Permanently deletes a file on remote machine.
    public void Delete()

    // Gets the full path of the directory or file.
    public string FullName { get; }

    // Gets or sets a value indicating whether the group members can execute this file.
    public bool GroupCanExecute { get; set; }

    // Gets or sets a value indicating whether the group members can read from this file.
    public bool GroupCanRead { get; set; }

    // Gets or sets a value indicating whether the group members can write into this file.
    public bool GroupCanWrite { get; set; }

    // Gets or sets file group id.
    public int GroupId { get; set; }

    // Gets a value indicating whether file represents a block device.
    public bool IsBlockDevice { get; }

    // Gets a value indicating whether file represents a character device.
    public bool IsCharacterDevice { get; }

    // Gets a value indicating whether file represents a directory.
    public bool IsDirectory { get; }

    // Gets a value indicating whether file represents a named pipe.
    public bool IsNamedPipe { get; }

    // Gets a value indicating whether file represents a regular file.
    public bool IsRegularFile { get; }

    // Gets a value indicating whether file represents a socket.
    public bool IsSocket { get; }

    // Gets a value indicating whether file represents a symbolic link.
    public bool IsSymbolicLink { get; }

    // Gets or sets the time the current file or directory was last accessed.
    public DateTime LastAccessTime { get; set; }

    // Gets or sets the time, in coordinated universal time (UTC), the current file or directory was last accessed.
    public DateTime LastAccessTimeUtc { get; set; }

    // Gets or sets the time when the current file or directory was last written to.
    public DateTime LastWriteTime { get; set; }

    // Gets or sets the time, in coordinated universal time (UTC), when the current file or directory was last written to.
    public DateTime LastWriteTimeUtc { get; set; }

    // Gets or sets the size, in bytes, of the current file.
    public long Length { get; }

    // Moves a specified file to a new location on remote machine, providing the option to specify a new file name.
    public void MoveTo(string destFileName)

    // For files, gets the name of the file. For directories, gets the name of the last directory in the hierarchy if a hierarchy exists.
    // Otherwise, the Name property gets the name of the directory.
    public string Name { get; }

    // Gets or sets a value indicating whether the others can execute this file.
    public bool OthersCanExecute { get; set; }

    // Gets or sets a value indicating whether the others can read from this file.
    public bool OthersCanRead { get; set; }

    // Gets or sets a value indicating whether the others can write into this file.
    public bool OthersCanWrite { get; set; }

    // Gets or sets a value indicating whether the owner can execute this file.
    public bool OwnerCanExecute { get; set; }

    // Gets or sets a value indicating whether the owner can read from this file.
    public bool OwnerCanRead { get; set; }

    // Gets or sets a value indicating whether the owner can write into this file.
    public bool OwnerCanWrite { get; set; }

    // Sets file  permissions.
    public void SetPermissions(short mode)

    // Returns a <xref href="System.String" data-throw-if-not-resolved="false"></xref> that represents this instance.
    public override string ToString()

    // Updates file status on the server.
    public void UpdateStatus()

    // Gets or sets file user id.
    public int UserId { get; set; }
}
```

**Members of Ssh.Tools.Sftp.SftpFileAttributes**
```csharp
public class SftpFileAttributes {
    // Gets or sets the extensions.
    public IDictionary<string, string> Extensions { get; }

    // Returns a byte array representing the current <xref href="UnderAutomation.UniversalRobots.Ssh.Tools.Sftp.SftpFileAttributes" data-throw-if-not-resolved="false"></xref>.
    public byte[] GetBytes()

    // Gets a value indicating whether the group members can execute this file.
    public bool GroupCanExecute { get; set; }

    // Gets a value indicating whether the group members can read from this file.
    public bool GroupCanRead { get; set; }

    // Gets a value indicating whether the group members can write into this file.
    public bool GroupCanWrite { get; set; }

    // Gets or sets file group id.
    public int GroupId { get; set; }

    // Gets a value indicating whether file represents a block device.
    public bool IsBlockDevice { get; }

    // Gets a value indicating whether file represents a character device.
    public bool IsCharacterDevice { get; }

    // Gets a value indicating whether file represents a directory.
    public bool IsDirectory { get; }

    // Gets a value indicating whether file represents a named pipe.
    public bool IsNamedPipe { get; }

    // Gets a value indicating whether file represents a regular file.
    public bool IsRegularFile { get; }

    // Gets a value indicating whether file represents a socket.
    public bool IsSocket { get; }

    // Gets a value indicating whether file represents a symbolic link.
    public bool IsSymbolicLink { get; }

    // Gets or sets the local time the current file or directory was last accessed.
    public DateTime LastAccessTime { get; set; }

    // Gets or sets the UTC time the current file or directory was last accessed.
    public DateTime LastAccessTimeUtc { get; set; }

    // Gets or sets the local time when the current file or directory was last written to.
    public DateTime LastWriteTime { get; set; }

    // Gets or sets the UTC time when the current file or directory was last written to.
    public DateTime LastWriteTimeUtc { get; set; }

    // Gets a value indicating whether the others can execute this file.
    public bool OthersCanExecute { get; set; }

    // Gets a value indicating whether the others can read from this file.
    public bool OthersCanRead { get; set; }

    // Gets a value indicating whether the others can write into this file.
    public bool OthersCanWrite { get; set; }

    // Gets a value indicating whether the owner can execute this file.
    public bool OwnerCanExecute { get; set; }

    // Gets a value indicating whether the owner can read from this file.
    public bool OwnerCanRead { get; set; }

    // Gets a value indicating whether the owner can write into this file.
    public bool OwnerCanWrite { get; set; }

    // Sets the permissions.
    public void SetPermissions(short mode)

    // Gets or sets the size, in bytes, of the current file.
    public long Size { get; set; }

    // Gets or sets file user id.
    public int UserId { get; set; }
}
```

## What to read next

- [Transfer files and backups](/universal-robots/documentation/how-to-transfer-files): a backup of the programs and the upload of a program.
- [Program and installation files](/universal-robots/documentation/archive-file): open and change a `.urp` file on the PC.