A lightweight Arduino/embedded library to expose a device filesystem over FTP, allowing uploads, downloads and remote file management from standard FTP clients (FileZilla, WinSCP, Explorer, etc.). This version supports a single FTP session.
Author: Renzo Mischianti Website: www.mischianti.org GitHub: xreef/SimpleFTPServer
Complete tutorials and platform-specific guides by the author are available on mischianti.org.
- π Simple FTP Server Library Home - Main library page with articles and examples
- π FTP server on ESP8266 and ESP32 - Getting started guide
- π Simple FTP server library now with support for Wio Terminal and SD
- Features
- Supported Platforms
- Supported Network Interfaces
- Supported Storage Systems
- Installation
- Basic Usage
- Configuration
- Included Examples
- Changelog
- License
- Contributing
- Support & Contact
- Expose device filesystem via a single FTP session (upload, download, delete, rename, list)
- Resume support (REST) and RFC-like commands (ALLO, STAT, SYST, HELP)
- Passive (
PASV,EPSV) and active (PORT) data connections - A second client (e.g. a FileZilla transfer connection) is accepted when the current session is idle (ESP32/ESP8266 WiFi)
- UTF-8 filename support (configurable)
- Configurable buffers and timeouts via
FtpServerKey.h - Works with internal flash filesystems (SPIFFS, LittleFS, FFAT) and external SD (SD, SdFat)
- Small footprint and simple API:
begin()andhandleFTP()
| Platform | Filesystems | Notes |
|---|---|---|
| ESP32 | SPIFFS, LittleFS, FFAT, SD, SD_MMC | Full support, see examples |
| ESP8266 | SPIFFS, LittleFS, SD | Limited RAM vs ESP32 |
| RP2040 / Pico W | LittleFS, SD | See Pico W examples |
| STM32 | SdFat, SPI flash | Use SdFat examples |
| Arduino (AVR) | SD (8.3), SdFat | Mega 2560 + W5100/W5500 shield; use SdFat for better compatibility |
| Arduino SAMD (Nano 33 IoT, MKR WiFi 1010) | SD, SdFat | WiFiNINA (firmware >= 1.5.0), see Arduino_WiFiNINA_SD |
| Arduino UNO R4 WiFi | SD (8.3) | WiFiS3 + SPI microSD module (CS pin in SD.begin()) |
| Wio Terminal | SdFat, Seed SD, native FAT | See Wio examples |
β οΈ Note: Some older AVR boards (Uno/Mega) have limited RAM and may not support large transfers.
- WiFi (ESP32, ESP8266, RP2040-W, WiFiNINA, WiFiS3 on Arduino UNO R4 WiFi)
- Ethernet (W5x00, W5500, ENC28J60, ESP32-ETH)
- Seeed RTL8720DN
- SPIFFS (ESP8266/ESP32)
- LittleFS (ESP8266/ESP32/RP2040)
- FFAT (ESP32)
- SD (Arduino SD library)
- SdFat / SdFat2 (recommended)
- SD_MMC (ESP32)
- Adafruit_SPIFlash
- Open Arduino IDE
- Sketch > Include Library > Manage Libraries
- Search for "SimpleFTPServer" and install
- Copy the repository folder into your Arduino
libraries/folder - Restart Arduino IDE
Add to platformio.ini:
lib_deps = xreef/SimpleFTPServer#include <WiFi.h>
#include "SPIFFS.h"
#include <SimpleFTPServer.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASS";
FtpServer ftpSrv;
void setup(){
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected. IP: ");
Serial.println(WiFi.localIP());
// Mount filesystem before starting FTP
if (SPIFFS.begin(true)) {
Serial.println("SPIFFS opened!");
// username, password for ftp.
ftpSrv.begin("esp32","esp32");
}
}
void loop(){
ftpSrv.handleFTP();
}See FtpServerKey.h for config defines and defaults. Key settings:
FTP_BUF_SIZEβ transfer buffer sizeFTP_TIME_OUTβ inactivity timeout (seconds)FTP_AUTH_TIME_OUTβ authentication timeout (seconds)FTP_DATA_CONNECT_TIMEOUT_MSβ max wait for the data connection, passive or active (default5000);handleFTP()blocks meanwhile, so keep it well below the client timeout (FileZilla: 20 s)FTP_TRANSFER_STALL_TIMEOUT_MSβ an upload with no data for this time is aborted with426(default10000)FTP_DATA_CLOSE_TIMEOUT_MSβNETWORK_W5100only: max wait for the client to close the data connection at the end of a transfer before the Ethernet library resets it (default5000; with the library default of 1 s a slow client lost the end of the file)FTP_IDLE_PREEMPT_MSβ ESP32/ESP8266 WiFi only: when another client is waiting and the logged-in session has been idle for this time, the idle session is closed and the new client accepted (default1500,0disables it)FTP_SERVER_DEBUGβ enable debug messages (e.g.-D FTP_SERVER_DEBUGinbuild_flags)DEBUG_PRINTERβ debug output stream (defaults toSerial)UTF8_SUPPORTβ enable/disable UTF-8 support
Prefer passive mode (the FileZilla default). In active mode (PORT) the board opens the data connection towards the PC, so the PC firewall must accept incoming connections for the FTP client on the network profile in use: on Windows a rule that allows FileZilla only on Public networks blocks it on a Private one, and every listing or transfer fails with 425 No data connection after a few seconds.
With WiFiNINA (Arduino Nano 33 IoT, MKR WiFi 1010) the NINA module can close an active-mode data connection while the board is sending to a slower receiver: the server answers 426 and the transfer has to be repeated. Passive mode is not affected.
See the examples/ folder for ready-to-use sketches for many platforms (ESP32, ESP8266, RP2040, STM32, Wio Terminal, Arduino). Adapt SSID, credentials and SD pins as needed.
-
2026-10-23 3.0.4
- Add
FTP_DATA_CONNECT_TIMEOUT_MS,FTP_TRANSFER_STALL_TIMEOUT_MSandFTP_IDLE_PREEMPT_MSinFtpServerKey.h: waiting for the passive/active data connection no longer blockshandleFTP()beyond the FileZilla timeout (it was up to 60 s) - Non-blocking
doStore(): a pause during an upload no longer ends it with226and a truncated file; an upload with no data forFTP_TRANSFER_STALL_TIMEOUT_MSis aborted with426 - Idle-session preemption (ESP32/ESP8266 WiFi): a waiting client (e.g. a FileZilla transfer connection) is accepted when the logged-in session is idle, instead of waiting up to
FTP_TIME_OUT readChar()reads the whole available command line in one call- A failed
STOR(425, e.g. active mode blocked by the PC firewall) no longer deletes or truncates the existing file - An interrupted download is reported with
426instead of226indoRetrieve()(e.g. WiFiNINA in active mode) - A complete download is no longer reported with
426when the client closes the data connection right after the last byte (e.g. curl) NETWORK_W5100: downloads to slow clients no longer lose the end of the file (EthernetClient::stop()reset the connection after 1 s); newFTP_DATA_CLOSE_TIMEOUT_MS- Fix ESP32/ESP8266 + Ethernet (
W5100,ENC28J60) build:setNoDelay()only with the ESPWiFiClient - Add
NETWORK_WiFiS3(Arduino UNO R4 WiFi)
- Add
-
2026-10-17 3.0.3
- Add RFC 2428
EPSV(Extended Passive Mode) command andFEATannouncement withWiFiNINAsocket reuse guard (#99) - Fix partial TCP write rewind in
doRetrieve()whendata.write()writes fewer bytes than read from storage under TCP backpressure (#100) - Fix
FTP_TRANSFER_STOPcallback receiving an empty filename incloseTransfer()and preventreadChar()null-terminator overflow intocwdName(#98) - Fix
readChar()replacing single quotes (') with/in filenames instead of Windows backslashes (\) (#96) - Fix
WiFiClient::flush()deprecation warnings on ESP32 Arduino Core 3.3.7+ by removing redundant calls afterstop()and guarding with#if defined(ESP8266)(#94) - Fix
isDir()leakingthis->filehandle and misidentifying regular files as directories onSTORAGE_SD,STORAGE_LITTLEFS,STORAGE_FFAT, andSTORAGE_SD_MMC; send250 DeletedbeforeFTP_FREE_SPACE_CHANGEcallback inDELE(#92) - Fix
APPE(append) mode on ESP32STORAGE_SDandSTORAGE_SD_MMCinopenFile()("a"was overwritten with"w") (#90) - Fix
getFileModTime()onSTORAGE_SDand ESP32 VFS (MLSTcommand support across SD backends) - Fix RFC 3659
MLSDoutput format onSTORAGE_FFAT,STORAGE_LITTLEFS, andSTORAGE_SEEED_SD - Fix
WiFiNINA(NETWORK_WiFiNINA) server socket exhaustion andaccept()/available()handling on SAMD21 (Arduino Nano 33 IoT); addArduino_WiFiNINA_SDandESP32_SD_SdFat2examples - Avoid blocking
free()FAT cluster scans onFTP_CONNECT/FTP_DISCONNECTand onSdFatwhenMAINTAIN_FREE_CLUSTER_COUNTis disabled (#93) - Decouple
#ifndef DEFAULT_STORAGE_TYPE_*and#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_*guards inFtpServerKey.hand update all library examples (#90, #91)
- Add RFC 2428
-
2025-11-28 3.0.2
- Fix #elif define (#88)
- Fix on SPIFM getName
-
2025-11-22 3.0.1 Fix / Example:
- Add example
ESP32_SD_WiFidemonstrating SD (SPI) + WiFi usage with SimpleFTPServer. - Update ESP32 project example to initialize SD via SPI (SPI.begin() + SD.begin(CS)) and start the FTP server using the SD storage.
- Minor linter-friendly renames for example callbacks and improved example comments.
- Add example
-
2025-10-13 3.0.0 Fix:
- updated SdFat2 initialization for Arduino Mega; integrated W5500 initialization (example Arduino_Mega_W5500_SdFat2)
- Fix READ WRITE APPEND problem
- Fix ram usage
- Set correct buffer size (Dynamic and Static)
- Add FTP callbacks for connection events and file transfers; update data types for free space and transferred size
- Improve file-open handling (ensure reads start at file beginning), increase passive data connection wait time, add robust FFat dir create/remove (fallback to /ffat and POSIX), add configurable minimum free-space check before uploads
- Refactor FTP callback functions to use uint32_t for space parameters, improve serial output, and register callbacks for FTP events
- Improve file-open handling (ensure reads start at file beginning), increase passive data connection wait time, add robust FFat dir create/remove (fallback to /ffat and POSIX), add configurable minimum free-space check before uploads
- Refactor FTP callback functions to use uint32_t for space parameters, improve serial output, and register callbacks for FTP events
-
2025-02-11 2.1.11 Management of relative and absolute path in command prompt (./ ../ /)
-
2025-01-28 2.1.11 Fix REST and add ALLO, and STAT commands
-
2025-01-13 2.1.11 Add addictional LOG to prevent multiple user issues
-
2025-01-12 2.1.11 Add REST (resume) command
-
2025-01-11 2.1.10 Multiple minor fix and optimization
-
2024-09-16 2.1.9 Fix LittleFS filename size.
-
2024-07-16 2.1.8 Add SYST command.
-
2023-10-07 2.1.7 Fix ESP32 rename on SD (thanks @scuba-hacker) #44
-
2023-02-02 2.1.6 Fix esp8266 Ethernet (w5x00) issue and explain solution for ESP32 Ethernet (w5x00), add new Networks management
-
2023-01-13 2.1.5 Fix SPIFM external SPI Flash date management (add SPIFM esp32 example)
-
2022-09-21 2.1.4 Add support for Raspberry Pi Pico W and rp2040 boards, Fix SD card config
-
2022-09-20 2.1.3 Soft AP IP management, more disconnect event and SD_MCC
-
2022-05-21 2.1.2 Fix SD path (#19)
-
2022-05-21 2.1.1 Minor fix
-
2022-03-30 2.1.0 Add UTF8 support and enabled It by default (Thanks to @plaber)
-
2022-03-30 2.0.0 Complete support for STM32 with SD and SPI Flash minor bux fix and HELP command support
-
2022-03-17 1.3.0 Fix enc28j60 and w5500 support and restructuring for local settings
-
2022-02-25 1.2.1 Fix anonymous user begin and fix SPIFFS wrong display
-
2022-02-22 1.2.0 Add anonymous user and implement correct RFC (#9 now work correctly with File Explorer)
-
2022-02-01 1.1.1 Add workaround to start FTP server before connection, add end and setLocalIP method.
MIT License β see LICENSE.md for details.
Copyright (c) 2017-2026 Renzo Mischianti
Contributions are welcome! Fork the repo, create a feature branch, commit and submit a Pull Request. Please ensure examples build on target platforms before opening a PR.
- Website: https://www.mischianti.org/category/my-libraries/simple-ftp-server/
- GitHub Issues: https://github.com/xreef/SimpleFTPServer/issues
- Forum: https://mischianti.org/forums/forum/mischiantis-libraries/simple-ftp-server/
- Articles: https://mischianti.org/category/my-libraries/simple-ftp-server/
Renzo Mischianti Website: https://www.mischianti.org Email: renzo.mischianti@gmail.com GitHub: @xreef
β If this library helped your project, please star the repository on GitHub!
