I've tried adding SimpleFTPServer to this example, which I've modified to create and leave some files and directories.
but when I access the unit via ftp (Filezilla) I just see an empty root directory.
Other ESP32 circuits I can FTP with no issues.
Can anyone help?
code below
#include "FS.h"
//#include "SPIFFS.h"
#include "LittleFS.h"
#include <time.h>
#include <WiFi.h>
#define SPIFFS LittleFS
/* This examples uses "quick re-define" of SPIFFS to run
an existing sketch with LittleFS instead of SPIFFS
You only need to format LittleFS the first time you run a
test or else use the LittleFS plugin to create a partition
https://github.com/lorol/arduino-esp32littlefs-plugin */
#define FORMAT_LITTLEFS_IF_FAILED true
#include <SimpleFTPServer.h>
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
const char *ssid = "xxx";
const char *password = "xxx";
/* Configuration of NTP */
#define MY_NTP_SERVER "pool.ntp.org"
long timezone = 1;
byte daysavetime = 1;
void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print(" DIR : ");
Serial.print(file.name());
time_t t = file.getLastWrite();
struct tm *tmstruct = localtime(&t);
Serial.printf(
" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour,
tmstruct->tm_min, tmstruct->tm_sec);
if (levels) {
listDir(fs, file.path(), levels - 1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.print(file.size());
time_t t = file.getLastWrite();
struct tm *tmstruct = localtime(&t);
Serial.printf(
" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour,
tmstruct->tm_min, tmstruct->tm_sec);
}
file = root.openNextFile();
}
}
void createDir(fs::FS &fs, const char *path) {
Serial.printf("Creating Dir: %s\n", path);
if (fs.mkdir(path)) {
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void removeDir(fs::FS &fs, const char *path) {
Serial.printf("Removing Dir: %s\n", path);
if (fs.rmdir(path)) {
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
void readFile(fs::FS &fs, const char *path) {
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while (file.available()) {
Serial.write(file.read());
}
file.close();
}
void writeFile(fs::FS &fs, const char *path, const char *message) {
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
void appendFile(fs::FS &fs, const char *path, const char *message) {
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if (!file) {
Serial.println("Failed to open file for appending");
return;
}
if (file.print(message)) {
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
void renameFile(fs::FS &fs, const char *path1, const char *path2) {
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
void deleteFile(fs::FS &fs, const char *path) {
Serial.printf("Deleting file: %s\n", path);
if (fs.remove(path)) {
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace) {
switch (ftpOperation) {
case FTP_CONNECT:
Serial.println(F("FTP: Connected!"));
break;
case FTP_DISCONNECT:
Serial.println(F("FTP: Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
Serial.printf("FTP: Free space change, free %u of %u!\n", freeSpace, totalSpace);
break;
default:
break;
}
};
void _transferCallback(FtpTransferOperation ftpOperation, const char *name, unsigned int transferredSize) {
switch (ftpOperation) {
case FTP_UPLOAD_START:
Serial.println(F("FTP: Upload start!"));
break;
case FTP_UPLOAD:
Serial.printf("FTP: Upload of file %s byte %u\n", name, transferredSize);
break;
case FTP_TRANSFER_STOP:
Serial.println(F("FTP: Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
Serial.println(F("FTP: Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
};
void setup() {
Serial.begin(115200);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Contacting Time Server");
configTime(0, 0, MY_NTP_SERVER); // --> Here is the IMPORTANT ONE LINER needed in your sketch!
while (time(nullptr) < 1600000000) { // wait for the first time sync
Serial.print("w");
delay(1000);
}
//configTime(3600 * timezone, daysavetime * 3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
struct tm tmstruct;
delay(2000);
tmstruct.tm_year = 0;
getLocalTime(&tmstruct, 5000);
Serial.printf(
"\nNow is : %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct.tm_year) + 1900, (tmstruct.tm_mon) + 1, tmstruct.tm_mday, tmstruct.tm_hour, tmstruct.tm_min,
tmstruct.tm_sec);
Serial.println("");
if (!SPIFFS.begin(FORMAT_LITTLEFS_IF_FAILED)) {
Serial.println("LittleFS Mount Failed");
return;
}
Serial.println("----list 1----");
listDir(SPIFFS, "/", 2);
//delete old files
deleteFile(SPIFFS, "/hello.txt");
deleteFile(SPIFFS, "/hello2.txt");
deleteFile(SPIFFS, "/mydir/hello2.txt");
Serial.println("----remove old dir----");
removeDir(SPIFFS, "/mydir");
Serial.println("----create a new dir----");
createDir(SPIFFS, "/mynewdir");
Serial.println("----create and work with file----");
writeFile(SPIFFS, "/hello.txt", "Hello this is a longer file");
writeFile(SPIFFS, "/mynewdir/hello.txt", "Hello ");
appendFile(SPIFFS, "/mynewdir/hello.txt", "World!\n");
Serial.println("----list 2----");
listDir(SPIFFS, "/", 2);
Serial.println("Test complete");
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
ftpSrv.begin("user", "password"); //username, password for ftp. (default 21, 50009 for PASV)
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
}
void loop() {
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}
there is also from the example ci.json tab
{
"requires_any": [
"CONFIG_SOC_WIFI_SUPPORTED=y",
"CONFIG_ESP_WIFI_REMOTE_ENABLED=y"
]
}
the serial moonitor shows all behaving correctly,
10:27:17.033 -> IP address:
10:27:17.033 -> 192.168.1.57
10:27:17.033 -> Contacting Time Server
10:27:17.033 -> w
10:27:20.011 -> Now is : 2025-03-30 09:27:16
10:27:20.011 ->
10:27:20.011 -> ----list 1----
10:27:20.011 -> Listing directory: /
10:27:20.011 -> FILE: hello.txt SIZE: 27 LAST WRITE: 2025-03-30 09:02:57
10:27:20.049 -> DIR : mydir LAST WRITE: 1969-12-31 23:59:59
10:27:20.049 -> Listing directory: /mydir
10:27:20.049 -> FILE: hello.txt SIZE: 13 LAST WRITE: 2025-03-30 09:00:11
10:27:20.083 -> DIR : mynewdir LAST WRITE: 1969-12-31 23:59:59
10:27:20.083 -> Listing directory: /mynewdir
10:27:20.083 -> FILE: hello.txt SIZE: 13 LAST WRITE: 2025-03-30 09:02:57
10:27:20.118 -> Deleting file: /hello.txt
10:27:20.118 -> File deleted
10:27:20.118 -> Deleting file: /hello2.txt
10:27:20.118 -> Delete failed
10:27:20.118 -> Deleting file: /mydir/hello2.txt
10:27:20.118 -> Delete failed
10:27:20.118 -> ----remove old dir----
10:27:20.118 -> Removing Dir: /mydir
10:27:20.118 -> rmdir failed
10:27:20.160 -> ----create a new dir----
10:27:20.160 -> Creating Dir: /mynewdir
10:27:20.160 -> Dir created
10:27:20.160 -> ----create and work with file----
10:27:20.160 -> Writing file: /hello.txt
10:27:20.160 -> File written
10:27:20.160 -> Writing file: /mynewdir/hello.txt
10:27:20.160 -> File written
10:27:20.195 -> Appending to file: /mynewdir/hello.txt
10:27:20.195 -> Message appended
10:27:20.195 -> ----list 2----
10:27:20.195 -> Listing directory: /
10:27:20.236 -> FILE: hello.txt SIZE: 27 LAST WRITE: 2025-03-30 09:27:17
10:27:20.236 -> DIR : mydir LAST WRITE: 1969-12-31 23:59:59
10:27:20.236 -> Listing directory: /mydir
10:27:20.236 -> FILE: hello.txt SIZE: 13 LAST WRITE: 2025-03-30 09:00:11
10:27:20.273 -> DIR : mynewdir LAST WRITE: 1969-12-31 23:59:59
10:27:20.273 -> Listing directory: /mynewdir
10:27:20.273 -> FILE: hello.txt SIZE: 13 LAST WRITE: 2025-03-30 09:27:17
10:27:20.313 -> Test complete
10:28:46.945 -> FTP: Connected!
10:33:48.060 -> FTP: Disconnected!