MultiFTPServer Library Tutorial for ESP32, Raspberry Pi Pico, Arduino, rp2040, esp8266 and STM32 (original) (raw)

Finally, we can say hello to MultiFTPServer, a lean, drop-in successor to SimpleFTPServer that finally brings true multi-session FTP to the hobby boards and industrial MCUs you love. With a single, unified API, you can now stream files to and from ESP8266, ESP32, STM32, classic Arduino boards, and the Raspberry Pi Pico W, all at the same time, all from the same sketch or firmware. Under the hood, the library adds an event-driven connection manager, smarter memory handling, and authentication hooks, so your data stays fast and safe even on devices with kilobytes to spare. In the pages ahead, we’ll unpack what changed, why parallel connections matter in real-world IoT workflows, and how to get MultiFTPServer running in minutes on your next project.

MultiFTPServer Library Tutorial

MultiFTPServer Library Tutorial

Toggle

Features

Why MultiFTPServer?

The new MultiFTPServer library addresses the limitations of SimpleFTPServer by allowing multiple simultaneous connections while maintaining a similar configuration structure. This makes it an ideal choice for applications requiring efficient file management over networks.

Library Availability

The MultiFTPServer library is available in the Arduino Library Manager. Search for “MultiFTPServer” and install it directly into your IDE.

ArduinoIDE MultiFTPServer Library

ArduinoIDE MultiFTPServer Library

You can also download the source code from GitHub:

For low-power MCUs that can’t handle multiple sessions, or if you simply don’t need concurrent sessions—stick with the reliable, time-tested SimpleFTPServer.

Configuration Options

MultiFTPServer supports various storage types and network configurations. Modify the FtpServerKey.h file to tailor the library to your project. Here are some options:

/********************************************************************************

/*******************************************************************************


** SETTINGS FOR FTP SERVER **


*******************************************************************************/

#ifndef FTP_SERVER_CONFIG_H #define FTP_SERVER_CONFIG_H

// Uncomment to enable printing out nice debug messages. // #define FTP_SERVER_DEBUG // #define FTP_ADDITIONAL_DEBUG

// Define where debug output will be printed. #define DEBUG_PRINTER Serial

#define STORAGE_SDFAT1 1 // Library SdFat version 1.4.x #define STORAGE_SDFAT2 2 // Library SdFat version >= 2.0.2 #define STORAGE_SPIFM 3 // Libraries Adafruit_SPIFlash and SdFat-Adafruit-Fork #define STORAGE_FATFS 4 // Library FatFs #define STORAGE_SD 5 // Standard SD library (suitable for Arduino esp8266 and esp32 #define STORAGE_SPIFFS 6 // SPIFFS #define STORAGE_LITTLEFS 7 // LITTLEFS #define STORAGE_SEEED_SD 8 // Seeed_SD library #define STORAGE_FFAT 9 // ESP32 FFAT #define STORAGE_SD_MMC 10 // SD_MMC library

#define NETWORK_ESP8266_ASYNC (1) #define NETWORK_ESP8266 (2) // Standard ESP8266WiFi #define NETWORK_ESP8266_242 (3) // ESP8266WiFi before 2.4.2 core #define NETWORK_W5100 (4) // Standard Arduino Ethernet library #define NETWORK_ETHERNET (4) // Standard Arduino Ethernet library #define NETWORK_ENC28J60 (5) // UIPEthernet library #define NETWORK_ESP32 (6) // Standard WiFi library #define NETWORK_RP2040_WIFI (15) // Raspberry Pi Pico W standard WiFi library #define NETWORK_ESP32_ETH (7) // Standard ETH library #define NETWORK_WiFiNINA (8) // Standard WiFiNINA library #define NETWORK_SEEED_RTL8720DN (9) // Standard SEED WiFi library #define NETWORK_ETHERNET_LARGE (10) #define NETWORK_ETHERNET_ENC (11) // EthernetENC library (evolution of UIPEthernet #define NETWORK_ETHERNET_STM (12) #define NETWORK_UIPETHERNET (13) // UIPEthernet library same of NETWORK_ENC28J60 #define NETWORK_ETHERNET_GENERIC (14) // Ethernet generic

// esp8266 configuration #ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266 #define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266 NETWORK_ESP8266 #define DEFAULT_STORAGE_TYPE_ESP8266 STORAGE_LITTLEFS #endif // esp32 configuration #ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 #define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 NETWORK_ESP32 #define DEFAULT_STORAGE_TYPE_ESP32 STORAGE_FFAT /** To use Ethernet.h with esp32 fix would be to change in Ethernet.h the line class EthernetServer : public Server { to class EthernetServer : public Stream {

or

in \esp32\2.0.6\cores\esp32\Server.h A workaround is to change line 28 of the ESP32 core's Server.h from: virtual void begin(uint16_t port=0) =0; to virtual void begin() =0; However, the last one, that will break anything that uses the ESP32 WiFi library's WebServer class.

https://github.com/arduino-libraries/Ethernet/issues/193 https://github.com/arduino-libraries/Ethernet/issues/88 * */ #endif // Standard AVR Arduino configuration #ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO #define DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO NETWORK_W5100 #define DEFAULT_STORAGE_TYPE_ARDUINO STORAGE_SD #endif // STM32 configuration #ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32 #define DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32 NETWORK_W5100 #define DEFAULT_STORAGE_TYPE_STM32 STORAGE_SDFAT2 #endif // Raspberry Pi Pico (rp2040) configuration #ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_RP2040 #define DEFAULT_FTP_SERVER_NETWORK_TYPE_RP2040 NETWORK_RP2040_WIFI #define DEFAULT_STORAGE_TYPE_RP2040 STORAGE_LITTLEFS #endif

// Arduino SAMD21 like Arduino MKR Nano 33 IoT or Wio Terminal #ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO_SAMD // Wio Terminal // #define DEFAULT_FTP_SERVER_NETWORK_TYPE_SAMD NETWORK_SEEED_RTL8720DN // #define DEFAULT_STORAGE_TYPE_SAMD STORAGE_SEEED_SD

// Arduino SAMD #define DEFAULT_FTP_SERVER_NETWORK_TYPE_SAMD NETWORK_WiFiNINA #define DEFAULT_STORAGE_TYPE_SAMD STORAGE_SD #endif

#define UTF8_SUPPORT

//#define SD_CS_PIN 4 // Disconnect client after 5 minutes of inactivity (expressed in seconds) #ifndef FTP_TIME_OUT #define FTP_TIME_OUT 5 * 60 #endif

// Wait for authentication for 10 seconds (expressed in seconds) #ifndef FTP_AUTH_TIME_OUT #define FTP_AUTH_TIME_OUT 10 #endif

// Size of file buffer for read/write // Transfer speed depends of this value // Best value depends on many factors: SD card, client side OS, ... // But it can be reduced to 512 if memory usage is critical. #ifndef FTP_BUF_SIZE #define FTP_BUF_SIZE 1024 //2048 //1024 // 512 #endif // Define the maximum number of concurrent sessions #ifndef FTP_MAX_SESSIONS #define FTP_MAX_SESSIONS 2 #endif

#endif // FTP_SERVER_CONFIG_H

Adjust these definitions to match your hardware setup.

For example the ESP32 section

#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 #define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 NETWORK_ESP32 #define DEFAULT_STORAGE_TYPE_ESP32 STORAGE_FFAT #endif

Allow to define the network by changing the value by changing the value of this line.

#define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 		NETWORK_ESP32

There are a large set of values, but only some are allowed for a specified microcontroller family.

#define NETWORK_ESP8266_ASYNC (1) #define NETWORK_ESP8266 (2) // Standard ESP8266WiFi #define NETWORK_ESP8266_242 (3) // ESP8266WiFi before 2.4.2 core #define NETWORK_W5100 (4) // Standard Arduino Ethernet library #define NETWORK_ETHERNET (4) // Standard Arduino Ethernet library #define NETWORK_ENC28J60 (5) // UIPEthernet library #define NETWORK_ESP32 (6) // Standard WiFi library #define NETWORK_RP2040_WIFI (15) // Raspberry Pi Pico W standard WiFi library #define NETWORK_ESP32_ETH (7) // Standard ETH library #define NETWORK_WiFiNINA (8) // Standard WiFiNINA library #define NETWORK_SEEED_RTL8720DN (9) // Standard SEED WiFi library #define NETWORK_ETHERNET_LARGE (10) #define NETWORK_ETHERNET_ENC (11) // EthernetENC library (evolution of UIPEthernet #define NETWORK_ETHERNET_STM (12) #define NETWORK_UIPETHERNET (13) // UIPEthernet library same of NETWORK_ENC28J60 #define NETWORK_ETHERNET_GENERIC (14) // Ethernet generic

Samething for the reference filesystem.

#define DEFAULT_STORAGE_TYPE_ESP32 					STORAGE_FFAT

By default the value is FFAT, but you can chose from this list some other values.

#define STORAGE_SDFAT1 1 // Library SdFat version 1.4.x #define STORAGE_SDFAT2 2 // Library SdFat version >= 2.0.2 #define STORAGE_SPIFM 3 // Libraries Adafruit_SPIFlash and SdFat-Adafruit-Fork #define STORAGE_FATFS 4 // Library FatFs #define STORAGE_SD 5 // Standard SD library (suitable for Arduino esp8266 and esp32 #define STORAGE_SPIFFS 6 // SPIFFS #define STORAGE_LITTLEFS 7 // LITTLEFS #define STORAGE_SEEED_SD 8 // Seeed_SD library #define STORAGE_FFAT 9 // ESP32 FFAT #define STORAGE_SD_MMC 10 // SD_MMC library

The most used alternatives for ESP32 are LittleFS, SPIFFS (standard for the old core), and naturally SD.

Features in Detail

Multi-Session Support

To enable multiple sessions, configure the FTP_MAX_SESSIONS parameter in the configuration:

#define FTP_MAX_SESSIONS 2

This allows two concurrent FTP sessions.

Debugging

Enable debugging to print detailed logs:

#define FTP_SERVER_DEBUG #define FTP_ADDITIONAL_DEBUG

Debug messages are printed to Serial. You can change the debug output by redefining DEBUG_PRINTER:

#define DEBUG_PRINTER Serial

Buffer Size

The buffer size determines transfer speed and memory usage. Configure it in the configuration file:

#define FTP_BUF_SIZE 1024

Authentication Timeout

Set the timeout for user authentication:

#define FTP_AUTH_TIME_OUT 10

Session Timeout

Set the timeout for inactive sessions:

UTF-8 Filename Support

UTF-8 filenames are supported by default. Ensure UTF8_SUPPORT is defined in the configuration file.

Examples

The default configuration for ESP32 uses the FFat filesystem, and here is an example of an FTP server.

/*

#include <Arduino.h> #include <FS.h> #include <FFat.h> #include <WiFi.h> #include <MultiFTPServer.h>

// WiFi credentials const char* WIFI_SSID = "reef-casa-sopra"; // Replace with your WiFi SSID const char* WIFI_PASSWORD = "aabbccdd77"; // Replace with your WiFi password

// FTP server instance FtpServer ftpServer;

void setup() { // Initialize Serial Monitor Serial.begin(115200); Serial.println("Initializing...");

// Connect to WiFi network Serial.printf("Connecting to WiFi: %s\n", WIFI_SSID); WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

// Wait for WiFi connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi connected!"); Serial.printf("Connected to: %s\n", WIFI_SSID); Serial.printf("IP Address: %s\n", WiFi.localIP().toString().c_str());

// Initialize FFat file system Serial.println("Initializing FFat file system..."); if (FFat.begin(true)) { // Auto-format FFat if not already formatted Serial.println("FFat initialized successfully!"); Serial.println("Formatting FFat..."); FFat.format(); // Optional: Format FFat (use only if needed) } else { Serial.println("Failed to initialize FFat!"); return; // Stop further execution if FFat initialization fails }

// Start FTP server ftpServer.begin("user", "password"); // Set FTP username and password Serial.println("FTP server started!"); Serial.println("You can now access the FFat file system via FTP."); }

void loop() { // Handle FTP server requests ftpServer.handleFTP(); // Continuously process FTP requests }

FTP Server on ESP32 and SD card

Here is a little sketch to manage the SD card FTP Server with ESP32

ESP32 SD adapter wiring breadboard

ESP32 SD adapter wiring breadboard

To put on work you must change configuration like so.

#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 #define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 NETWORK_ESP32 #define DEFAULT_STORAGE_TYPE_ESP32 STORAGE_SD #endif

And here the code.

/*

#include <WiFi.h> #include <MultiFTPServer.h> #include <SPI.h> #include <SD.h>

// WiFi credentials const char* WIFI_SSID = ""; // Replace with your WiFi SSID const char* WIFI_PASSWORD = ""; // Replace with your WiFi password

// SD card chip select pin const int CHIP_SELECT_PIN = SS; // Default SS pin for SPI

// FTP server instance FtpServer ftpServer;

void setup() { // Initialize Serial Monitor Serial.begin(9600); while (!Serial) { // Wait for serial port to connect (required for native USB ports) }

// Connect to WiFi network Serial.println("Connecting to WiFi..."); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi connected!"); Serial.printf("Connected to: %s\n", WIFI_SSID); Serial.printf("IP Address: %s\n", WiFi.localIP().toString().c_str());

// Wait for a short delay before initializing SD card delay(1000);

// Initialize SD card Serial.print("Initializing SD card..."); while (!SD.begin(CHIP_SELECT_PIN)) { delay(500); Serial.print("."); } Serial.println("\nSD card initialized successfully!");

// Start FTP server with username and password ftpServer.begin("user", "password"); // Replace with your desired FTP credentials Serial.println("FTP server started!"); }

void loop() { // Handle FTP server operations ftpServer.handleFTP(); // Continuously process FTP requests }

esp32 sd card adapter connection

esp32 sd card adapter connection

Add a status callback to your FTP Server

The library offer the opportunity to add some callback to check the state of connection or transfer.

The signs of the functions are:

void (_callback)(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){}; void (_transferCallback)(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){};

Main callback

The first is called when one of these operation is executed:

The other parameters are:

Transfer callback

The second one when these operation are executed:

The other parameters are:

Example sketch with callback

The resulting code with callbacks can be:

/*

#include "FS.h" #include "FFat.h" #include <WiFi.h> #include <MultiFTPServer.h>

// WiFi credentials const char* ssid = "reef-casa-sopra"; const char* password = "aabbccdd77";

// FTP server instance FtpServer ftpSrv;

/**

/**

void setup() { // Initialize serial communication Serial.begin(115200);

// Connect to WiFi Serial.println(F("Connecting to WiFi...")); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi connected!"); Serial.print(F("IP Address: ")); Serial.println(WiFi.localIP());

// Initialize FFat file system Serial.print(F("Initializing FFat filesystem...")); if (FFat.begin(true)) { Serial.println(F("done.")); } else { Serial.println(F("failed! Please check FFat setup.")); while (true) { delay(1000); } }

// Set FTP server callbacks ftpSrv.setCallback(ftpOperationCallback); ftpSrv.setTransferCallback(ftpTransferCallback);

// Start FTP server with username and password Serial.println(F("Starting FTP server...")); ftpSrv.begin("user", "password"); // Username: "user", Password: "password" }

void loop() { // Handle FTP server operations ftpSrv.handleFTP(); }

Here the serial output of upload a file and delete 2 files:

Connecting to WiFi... ..... WiFi connected! IP Address: 192.168.1.57 Initializing FFat filesystem...done. Starting FTP server... FTP: Client connected! FTP: Started uploading file: api-82.jar FTP: Uploading file: api-82.jar, Transferred: 1024 bytes FTP: Uploading file: api-82.jar, Transferred: 2048 bytes FTP: Uploading file: api-82.jar, Transferred: 3072 bytes FTP: Uploading file: api-82.jar, Transferred: 4096 bytes FTP: Uploading file: api-82.jar, Transferred: 5120 bytes FTP: Uploading file: api-82.jar, Transferred: 6144 bytes FTP: Uploading file: api-82.jar, Transferred: 7168 bytes FTP: Uploading file: api-82.jar, Transferred: 8192 bytes FTP: Uploading file: api-82.jar, Transferred: 9216 bytes FTP: Uploading file: api-82.jar, Transferred: 10240 bytes FTP: Uploading file: api-82.jar, Transferred: 11264 bytes FTP: Uploading file: api-82.jar, Transferred: 12288 bytes FTP: Uploading file: api-82.jar, Transferred: 13312 bytes FTP: Uploading file: api-82.jar, Transferred: 14336 bytes FTP: Uploading file: api-82.jar, Transferred: 15360 bytes FTP: Uploading file: api-82.jar, Transferred: 16384 bytes FTP: Uploading file: api-82.jar, Transferred: 17408 bytes FTP: Uploading file: api-82.jar, Transferred: 18432 bytes FTP: Uploading file: api-82.jar, Transferred: 19456 bytes FTP: Uploading file: api-82.jar, Transferred: 20480 bytes FTP: Uploading file: api-82.jar, Transferred: 21504 bytes FTP: Uploading file: api-82.jar, Transferred: 22528 bytes FTP: Uploading file: api-82.jar, Transferred: 23552 bytes FTP: Uploading file: api-82.jar, Transferred: 24576 bytes FTP: Uploading file: api-82.jar, Transferred: 25478 bytes FTP: Transfer completed successfully. FTP: Free space changed. Free: 1261568 bytes, Total: 10240000 bytes. FTP: Free space changed. Free: 3510272 bytes, Total: 10240000 bytes. FTP: Free space changed. Free: 10211328 bytes, Total: 10240000 bytes.

We are going to analize the output:

Supported Platforms

The MultiFTPServer library supports the following platforms:

Platform Network Type Default Storage
ESP8266 WiFi, Ethernet SPIFFS, SPIflash, LittleFS and SD
ESP32 WiFi, Ethernet SPIFFS, SPI Flash, LittleFS, FFat and SD
Arduino Ethernet, WiFiNINA, WiFi, External WiFi SD, SPI Flash, SdFat1 and SdFat2
STM32 Ethernet, External WiFi SPI Flash, SdFat2
Raspberry Pi Pico Ethernet, WiFi (RP2040) and External WiFi LittleFS, SPI Flash, SdFat2 and SD

Configure client

When you configure your client, pay attention to the “Maximun number of connections:” that must be the same as the number specified in the library.

I use FileZilla as client, you can download It here, It quite simple to use and configure.

Filezilla configuration for access esp8266, select plain FTP on Manage Site

First you must go on Manage site --> New site and now set this parameter:

Filezilla configuration for access esp8266, select max num connections

If you want to transfer big file, you must extend timeout time.

Thanks

  1. SimpleFTPServer library: esp32 and esp8266 how to
  2. SimpleFTPServer library: WioTerminal how to
  3. FTP server on STM32 with w5500, enc28j60, SD Card, and SPI Flash
  4. MultiFTPServer Library Tutorial for ESP32, Raspberry Pi Pico, Arduino, rp2040, esp8266 and STM32