Hi Renzo,
I hope you are well,
Did you find some time to investigate in this project?
I’m so excited to “drag and drop” files from FTP (FileZilla) to the internal SPIFFS memory of my ESP32, can’t wait to be able to do the same with the External memory.
Waiting for your reply, if you need that i do some tests, let me know!
Thanks a lot,
Frederic.
Hi Renzo,
I’m back after some tests.
I think i don’t have missing dependencies.
I’ve been back to VSC, as the Arduino IDO does not give me enough details on what’s going wrong.
I’ve managed to make the code to compile properly, all the above errors where removed, by adding this line:
#include <FS.h> in FTPserver.h file, as show in picture A.
I don’t know if it’s a hasard, cause i told you, i don’t know libraries, but it seems to solve the problem…
So i could upload it to my ESP32S3, but that codes makes my ESP32S3 reboot continuously.
I’ve tried today with an old ESP32 (NodeMCU 32S), and still have the same behaviour.
You will find in picture B, the output on the serial monitor.
The ESP32 still reboot.
Something not liked in the code, but what…?
If you have an idea?
Thanks a lot,
Frederic.
Hi Renzo,
Well, no luck.
Still the same errors.
I’m running the Arduino IDE 2.0.3.
I’ve tried to install an old version of Arduino IDE (1.0.5), but i even can’t install the ESP32-S3 board…
I have uinstalled all the libraries, and install them again, same result.
What puzzles me is the difference between your output and mine.
I only have the errors of syntax, but i don’t have all the detail of your libraries downloaded.
What i can see on your output is (picture attached), that the libraries Wifi and SPI seem to be “apart”.
I have on the left column my Libraries (see picture attached):
SimpleFTPServer 2.1.5: matchs with your output.
SdFat Addafruit 2.2.1: matchs with your output.
Adafruit SPIFlash 4.0.0: matchs with your output. But i don’t have the SPI and WIFI ones.
If i Ctl+Clic on the #include <Wifi>, i can open a Wifi.h.
So i guess i have the Wifi library.
So first i could crosscheck the content of this file with yours? But how to access the SPI.h? Seems to be missing.
I’m so sorry to take so much of your time, but i would really like to make this happen.
Thanks,
Frederic.
Hi Renzo,
Thanks for your answer. That’s what i did two days ago with same issue.
I made a new try right now.
I give you a screenshot of my IDE interface, and you can see on the left the libraries installed.
Can you provide me your settings/libraries so i can investigate what is going wrong?
Thanks a lot,
Frederic.
Hi Renzo,
I did a brand new installation, creating a new project, with libraries empty.
I added in my “platformIO.ini” the following libraries (pict LIB_1):
lib_deps =
# RECOMMENDED
# Accept new functionality in a backwards compatible manner and patches
adafruit/SdFat – Adafruit Fork @ ^2.2.1
adafruit/Adafruit SPIFlash @ ^4.0.0
xreef/SimpleFTPServer @ ^2.1.4
After compiling, the libraries are “charged” automatically and appear in my left column.
Here are two screenshots of my left column where there is the list of folders linked to my project.
You can see that there are two main folders:
Picture LIB_2: folder ESP32S3BOX.
Picture LIB_3: folder libdeps\ESP32S3BOX
You can see on the pictures which libraries are “charged”.
I hope this can help you to understand where things go wrong.
Maybe the “library” instead of <library> should be used?
Thanks a lot,
Frederic.
Hi Renzo,
Thanks a lot for your time in this project.
I’ve tested your code, but still have the same errors.
I have modified the “FTPServerKey.h” with the SPIFM parameter but still.
Here are the errors above, and also screenshots from the “FTPServer.cpp”if it can help you…?
Something linked to the Definition of “File” or “file”?
(I told you, i don’t understand very well how library work…)
Can’t wait for your reply!
Thanks again,
Frederic.
Errors (9) after compiling code:
In file included from .pio/libdeps/esp32s3box/SimpleFTPServer/SimpleFTPServer.h:14,
from src/main.cpp:17:
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:419:18: error: ‘File’ has not been declared
#define FTP_DIR File
^~~~
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:560:20: note: in expansion of macro ‘FTP_DIR’
bool openDir( FTP_DIR * pdir
);
^~~~~~~
In file included from .pio/libdeps/esp32s3box/SimpleFTPServer/SimpleFTPServer.h:14,
from src/main.cpp:17:
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:573:15: error: expected ‘;’ at end of member declaration
const char* getFileName(FTP_FILE *file){
^~~~~~~~~~~
;
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:573:36: error: expected ‘)’ before ‘*’ token
const char* getFileName(FTP_FILE *file){
~
^
In file included from .pio/libdeps/esp32s3box/SimpleFTPServer/SimpleFTPServer.h:14,
from src/main.cpp:17:
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:418:19: error: ‘File’ has not been declared
#define FTP_FILE File
^~~~
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:627:22: note: in expansion of macro ‘FTP_FILE’
uint32_t fileSize( FTP_FILE file );
^~~~~~~~
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:418:19: error: ‘File’ does not name a type; did you mean ‘SdFile’?
#define FTP_FILE File
^~~~
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:702:3: note: in expansion of macro ‘FTP_FILE’
FTP_FILE file;
^~~~~~~~
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:419:18: error: ‘File’ does not name a type; did you mean ‘SdFile’?
#define FTP_DIR File
^~~~
.pio/libdeps/esp32s3box/SimpleFTPServer/FtpServer.h:703:3: note: in expansion of macro ‘FTP_DIR’
FTP_DIR dir;
^~~~~~~
*** [.pio\build\esp32s3box\src\main.cpp.o] Error 1
=== [FAILED] Took 15.92 seconds ===
Update:
I have used your simpleFTP server code, just to try.
It works perfectly when i leave STORAGE_SPIFFS in the “FTPServerKey.h” file.
So i can access via FileZilla to the SPIFFS data. I can upload a file, it’s just a “Waouu” for me.
But when i move to STORAGE_SPIFM, i got the errors in the “FTPServer.cpp” file.
Waiting for the “last step”!
Thanks,
Frederic.
Hi Renzo,
No worries for the delay of your answer, i’m so grateful that you try to help me!
So i did exactly what you suggested:
I replaced the “STORAGE_FFAT” by “STORAGE_SPIFM” in the “FTPServerkey.h”.
Then i added the libraries:
#include “SdFat.h”
#include “Adafruit_SPIFlash.h”
and yours: #include <SimpleFTPServer.h>
After compiling, i have a million errors in the “FTPServer.cpp” file (see picture attached, if you want all the errors, i can post them).
I definetely do something wrong with the libraries i guess…
As a reminder, i use the code above, not yours.
The one above seems to offer options like uploading, deleting.. (see second picture attached), that’s why i’m trying to make this one work.
Waiting for your reply, or someone else?
Grazie,
Frederic.
Hi all,
I’ll reply to my own post so i can share with you my code that for now works, but only to access INTERNAL flash memory.
This code creates an FTP Server, and i can access to the content of my internal flash memory (i understood the “SPIFFS” one).
I can see the content of my files (.txt) when requesting on the webbrowser: http://esp32fs.local/<nameoffile>.txt
I don’t know if i can upload files from the webbrowser (don’t know if it’s possible, the code seems to handle it?, and the syntax i should use).
But anyway, for me it’s a “progress”. So i come back again with my question, how to “point” to my external SPI flash W25Q64?
Thanks a lot for the person who could help me!
PS: Renzo, i’ve tried you FTPSimpleServer but i can’t get it work.
And i didnt get how to “set” what you advised here:
“you must set on EMailSenderKey.h file this define.
In this place (STM32 storage section).”
1/ because i did’nt find the EmailSenderKey.h,
2/ because i was waiting for a “MOSI=5” to change to “MOSI=11” as simple as that but not the case…
Here is the code:
/*
SKETCH pour lire les fichiers sur la mémoire SPIFFS
Vérifier que le wifi du garage est bien activé
Une fois le sketch lancé, l'ESP32 va se connecter au wifi du garage
Utiliser le serial monitor pour obtenir l'adresse IP de l'ESP32
Puis copier coller cette adresse dans un navigateur, en ajoutant à la suite le "/fichier à lire"
Le fichier s'ouvrira dans le navigateur
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#define FILESYSTEM SPIFFS
// You only need to format the filesystem once
#define FORMAT_FILESYSTEM false
#define DBG_OUTPUT_PORT Serial
#if FILESYSTEM == FFat
#include <FFat.h>
#endif
#if FILESYSTEM == SPIFFS
#include <SPIFFS.h>
#endif
const char *ssid = "WIFI_SSID";
const char *password = "PASSWORD";
const char *host = "esp32fs";
WebServer server(80);
//holds the current upload
File fsUploadFile;
//format bytes
String formatBytes(size_t bytes) {
if (bytes < 1024) {
return String(bytes) + "B";
} else if (bytes < (1024 * 1024)) {
return String(bytes / 1024.0) + "KB";
} else if (bytes < (1024 * 1024 * 1024)) {
return String(bytes / 1024.0 / 1024.0) + "MB";
} else {
return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
}
}
String getContentType(String filename) {
if (server.hasArg("download")) {
return "application/octet-stream";
} else if (filename.endsWith(".htm")) {
return "text/html";
} else if (filename.endsWith(".html")) {
return "text/html";
} else if (filename.endsWith(".css")) {
return "text/css";
} else if (filename.endsWith(".js")) {
return "application/javascript";
} else if (filename.endsWith(".png")) {
return "image/png";
} else if (filename.endsWith(".gif")) {
return "image/gif";
} else if (filename.endsWith(".jpg")) {
return "image/jpeg";
} else if (filename.endsWith(".ico")) {
return "image/x-icon";
} else if (filename.endsWith(".xml")) {
return "text/xml";
} else if (filename.endsWith(".pdf")) {
return "application/x-pdf";
} else if (filename.endsWith(".zip")) {
return "application/x-zip";
} else if (filename.endsWith(".gz")) {
return "application/x-gzip";
}
return "text/plain";
}
bool exists(String path) {
bool yes = false;
File file = FILESYSTEM.open(path, "r");
if (!file.isDirectory()) {
yes = true;
}
file.close();
return yes;
}
bool handleFileRead(String path) {
DBG_OUTPUT_PORT.println("handleFileRead: " + path);
if (path.endsWith("/")) {
path += "index.htm";
}
String contentType = getContentType(path);
String pathWithGz = path + ".gz";
if (exists(pathWithGz) || exists(path)) {
if (exists(pathWithGz)) {
path += ".gz";
}
File file = FILESYSTEM.open(path, "r");
server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
void handleFileUpload() {
if (server.uri() != "/edit") {
return;
}
HTTPUpload &upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
String filename = upload.filename;
if (!filename.startsWith("/")) {
filename = "/" + filename;
}
DBG_OUTPUT_PORT.print("handleFileUpload Name: ");
DBG_OUTPUT_PORT.println(filename);
fsUploadFile = FILESYSTEM.open(filename, "w");
filename = String();
} else if (upload.status == UPLOAD_FILE_WRITE) {
//DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
if (fsUploadFile) {
fsUploadFile.write(upload.buf, upload.currentSize);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (fsUploadFile) {
fsUploadFile.close();
}
DBG_OUTPUT_PORT.print("handleFileUpload Size: ");
DBG_OUTPUT_PORT.println(upload.totalSize);
}
}
void handleFileDelete() {
if (server.args() == 0) {
return server.send(500, "text/plain", "BAD ARGS");
}
String path = server.arg(0);
DBG_OUTPUT_PORT.println("handleFileDelete: " + path);
if (path == "/") {
return server.send(500, "text/plain", "BAD PATH");
}
if (!exists(path)) {
return server.send(404, "text/plain", "FileNotFound");
}
FILESYSTEM.remove(path);
server.send(200, "text/plain", "");
path = String();
}
void handleFileCreate() {
if (server.args() == 0) {
return server.send(500, "text/plain", "BAD ARGS");
}
String path = server.arg(0);
DBG_OUTPUT_PORT.println("handleFileCreate: " + path);
if (path == "/") {
return server.send(500, "text/plain", "BAD PATH");
}
if (exists(path)) {
return server.send(500, "text/plain", "FILE EXISTS");
}
File file = FILESYSTEM.open(path, "w");
if (file) {
file.close();
} else {
return server.send(500, "text/plain", "CREATE FAILED");
}
server.send(200, "text/plain", "");
path = String();
}
void handleFileList() {
if (!server.hasArg("dir")) {
server.send(500, "text/plain", "BAD ARGS");
return;
}
String path = server.arg("dir");
DBG_OUTPUT_PORT.println("handleFileList: " + path);
File root = FILESYSTEM.open(path);
path = String();
String output = "[";
if (root.isDirectory()) {
File file = root.openNextFile();
while (file) {
if (output != "[") {
output += ',';
}
output += "{\"type\":\"";
output += (file.isDirectory()) ? "dir" : "file";
output += "\",\"name\":\"";
output += String(file.name()).substring(1);
output += "\"}";
file = root.openNextFile();
}
}
output += "]";
server.send(200, "text/json", output);
}
void setup(void) {
DBG_OUTPUT_PORT.begin(115200);
DBG_OUTPUT_PORT.print("\n");
DBG_OUTPUT_PORT.setDebugOutput(true);
if (FORMAT_FILESYSTEM)
FILESYSTEM.format();
FILESYSTEM.begin();
{
File root = FILESYSTEM.open("/");
File file = root.openNextFile();
while (file) {
String fileName = file.name();
size_t fileSize = file.size();
DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(),
formatBytes(fileSize).c_str());
file = root.openNextFile();
}
DBG_OUTPUT_PORT.printf("\n");
}
//WIFI INIT
DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
if (String(WiFi.SSID()) != String(ssid)) {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
DBG_OUTPUT_PORT.print(".");
}
DBG_OUTPUT_PORT.println("");
DBG_OUTPUT_PORT.print("Connected! IP address: ");
DBG_OUTPUT_PORT.println(WiFi.localIP());
MDNS.begin(host);
DBG_OUTPUT_PORT.print("Open http://");
DBG_OUTPUT_PORT.print(host);
DBG_OUTPUT_PORT.println(".local/edit to see the file browser");
//SERVER INIT
//list directory
server.on("/list", HTTP_GET, handleFileList);
//load editor
server.on("/edit", HTTP_GET, []() {
if (!handleFileRead("/edit.htm")) {
server.send(404, "text/plain", "FileNotFound");
}
});
//create file
server.on("/edit", HTTP_PUT, handleFileCreate);
//delete file
server.on("/edit", HTTP_DELETE, handleFileDelete);
//first callback is called after the request has ended with all parsed arguments
//second callback handles file uploads at that location
server.on("/edit", HTTP_POST, []() {
server.send(200, "text/plain", "");
}, handleFileUpload);
//called when the url is not defined here
//use it to load content from FILESYSTEM
server.onNotFound([]() {
if (!handleFileRead(server.uri())) {
server.send(404, "text/plain", "FileNotFound");
}
});
//get heap status, analog input value and all GPIO statuses in one json call
server.on("/all", HTTP_GET, []() {
String json = "{";
json += "\"heap\":" + String(ESP.getFreeHeap());
json += ", \"analog\":" + String(analogRead(2));
json += ", \"gpio\":" + String((uint32_t) (0));
json += "}";
server.send(200, "text/json", json);
json = String();
});
server.begin();
DBG_OUTPUT_PORT.println("HTTP server started");
}
void loop(void) {
server.handleClient();
delay(2); //allow the cpu to switch to other tasks
}
This reply was modified 1 year, 4 months ago by Renzo Mischianti.
Author
Posts
Viewing 9 posts - 1 through 9 (of 9 total)
Follow:
More
Welcome to Our Family!
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.