ESP32-Ftp_Client Upload immagine da SD-CARD a FTP

Salve a tutti e scusate il disturbo.
Ho realizzato un progetto con la ESP32-CAM per la cattura ed il salvataggio delle immagini catturate.
Utilizzo la libreria : ESP32_FTPClient.h
Ho riscontrato un problema quando provo a copiare un'immagine jpg dalla SD-CARD all'area FTP.
L'immagine viene copiata correttamente ma è illeggibile.
Prima di provare a trovato aiuto qui, vi assicuro che ho cercato qualsiasi riferimento utile ma non sono riuscito a trovare nulla.

Allego la parte di codice che esegue questa operazione.

/************************************************/
/* RICERCA FOTO VIAGGIO DA TRASFERIRE           */
/************************************************/
void CerFotVia(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.println(file.name());
      if(levels)
      {
        CerFotVia(fs, file.path(), levels -1);
      }
    }
    else
    {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
      // Trasferimento Immagini del Viaggio
      NumDocCar +=1;
      TraFotVia(file.path(),file.size());
      // Cancellazione Documento Trasferito
      DelDocVia(SD_MMC,file.path());
    }  
    file = root.openNextFile();
  }
}

/************************************************/
/* CANCELLA DOCUMENTO VIAGGIO TRASFERITO SI FTP */
/************************************************/
void DelDocVia(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");
  }
} 

/************************************************/
/* AVVIA TRASFERIMENTO IMMAGINI                 */
/************************************************/
void TraFotVia(String NomFot,int DimFot)
{
  char Foto[40];
  boolean EsiConFtp = false;
  int NumTenTra = 0;

  // Forma Percorso Cartella Viaggio
  w0 = String(FTP_DIR) + String(DirViaTra) + "/";
  LW = w0.length()+1;
  w0.toCharArray(PatViaFtp, LW);

  Serial.printf("DirViaTra %s , PatViaFtp %s, DimFot %d NomFot , ",DirViaTra,PatViaFtp,DimFot);
  Serial.println(NomFot);

  ESP32_FTPClient ftp (FTP_SER,FTP_POR,FTP_USR,FTP_PWD, 5000, 2);

  // Apertura Immagine
  //w0 = String(DirViaTra) + "/" + NomFot;
  //Serial.println(w0);

  w0 = NomFot.substring(1);
  LW = w0.length()+1;
  w0.toCharArray(Foto, LW);

  while (EsiConFtp == false && NumTenTra < 3)
  {
  ftp.OpenConnection();
  if ( ftp.isConnected() )
    {        
      //ftp.ChangeWorkDir( PatViaFtp );        
      ftp.ChangeWorkDir( FTP_DIR );        
      ftp.InitFile("Type I");
      ftp.NewFile(Foto);
      ftp.WriteData( (unsigned char *)Foto,sizeof(Foto));
      ftp.CloseFile();
      ftp.CloseConnection();
      NumDocTra +=1;
      EsiConFtp = true;         
    }
    else
    {
      delay(500);
      NumTenTra+=1;
    }
  }
}

Buonasera e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

Salve e mi scusi. Farei volentieri la mia presentazione ma, mi creda, non riesco a capire dove inserire il posto. Sono mortificato e la prego di darmi una dritta. Cordiali Saluti.

Quello in blu è un link ... fai click e ti trovi nella discussione delle "presentazioni", li rispondi come rispondi in ogni discussione e fai, come gli altri, la tua presentazione :slight_smile:

Guglielmo

Dopo averle scritto, dovrei essere riuscito a fare quanto richiesto. Qualora non sia corretto la pregherei di indicarmelo.
Cordiali Saluti.

Va benissimo, grazie :slight_smile:

Guglielmo

:+1: :wave:

Qui c'è qualcosa che non va di sicuro...

Foto[] è un array di caratteri da 40 byte.. dubito che possa gestire il contenuto di un'immagine.

Non conosco la libreria in questione, ma a naso direi che WriteData() si aspetta un buffer di unsigned char ovvero in questo caso un riferimento al file dove è stata memorizzata l'immagine.

Salve e grazie per la collaborazione. La libreria, effettivamente riporta un esempio di upload fatto come segue

// Create the new file and send the image
  ftp.ChangeWorkDir("my_new_dir");
  ftp.InitFile("Type I");
  ftp.NewFile("octocat.jpg");
  ftp.WriteData( octocat_pic, sizeof(octocat_pic) );
  ftp.CloseFile();

dove octocat_pic fa riferimento ad file : octocat_pic.h che contiene, credo, la rappresentazione in HEX di un immagine come da esempio sotto riportato

// This is the GitHub Octocat in HEX in order to test the FTP Upload

unsigned char octocat_pic[] PROGMEM = {
  0xFF,0xD8,0xFF,0xE1,0x00,0x18,0x45,0x78,0x69,0x66,0x00,0x00,0x49,0x49,0x2A,0x00,
  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xEC,0x00,0x11,
  0x44,0x75,0x63,0x6B,0x79,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x50,0x00,0x00,0xFF,
  0xE1,0x03,0x2D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6E,0x73,0x2E,0x61,0x64,0x6F,
  0x62,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x78,0x61,0x70,0x2F,0x31,0x2E,0x30,0x2F,0x00,

per finire la funzione WriteData è la seguente

void ESP32_FTPClient::WriteData (unsigned char * data, int dataLength) {
  FTPdbgn(F("Writing"));
  if(!isConnected()) return;
  WriteClientBuffered(&dclient, &data[0], dataLength);
}

Purtroppo non ho trovato alcun esempio che illustrasse come eseguire l'upload di un'immagine registrata su SD-CARD. Ho provato a chiedere anche all'autore della libreria ma, con mio disappunto non ho ricevuto risposta. Da ultimo, qualsiasi, esempio con questa libreria o altre similari, riportano sempre l'upload come indicato sopra.

Si tratta di questa libreria immagino.

Francamente non mi sembra il massimo...
FTP è un protocollo basato sullo scambio di file, ma la libreria non offre alcun supporto alla classe File di Arduino e devi far passare tutto attaverso il buffer unsigned char clientBuf[1500] cosa che non offre molta flessibilità.

La cosa più semplice è leggere il contenuto del file salvandolo in un ulteriore tuo buffer (e sono 3, visto che il file svolge di fatto già la stessa funzione) che poi passi al metodo in questione.

La cosa migliore sarebbe aggiungere alla classe un ulteriore metodo WriteData() che accetta come parametro un'oggetto Stream (ovvero la classe base da cui è derivata la classe File).
Non è necessario riscrivere/modificare la libreria, basta creare una tua classe ereditata da ESP32_FTPClient al quale aggiungi il metodo mancante.

Ma cosa dovrebbe fare sto pezzo ? NON sappiamo cosa è LW, intero ?
Ma comunque quelle tre righe:

  1. prendi il nome del file partendo dal secondo carattere, e lo metti in w0
  2. calcoli la lunghezza del NOME del file (non del contenuto del file)
  3. scrivi dentro ad array Foto il NOME del file (mica il contenuto)

Come pretendi che un file che contiene il nome del file debba contenere una immagine?
Prova ad aprire quel file ottenuto con un editor e secondo me ci trovi un testo.

In Foto (ma 40 byte sono pochi, quanto sono grandi i tuoi jpg??) dovresti leggere attraverso comandi della libreria/classe File di Arduino il contenuto del file (come detto qui sopra da cotestatnt)

P.S. ma chi è l'autore del post ? BigGiu o 606405 ??

Concordo con il fatto che non sia il massimo. Io però non ho trovato nulla di meglio, o per essere più esplicito qualcosa che sia di facile comprensione, per me, ed utilizzo. Per quanto riguarda la tua soluzione, proverò a fare qualche esperimento anche se francamente non mi sono mai spinto a modificare librerie esistenti. Grazie per il tempo che mi hai dedicato, se poi vuoi fornirmi un codice esempio di quanto da te illustrato te ne sarei infinitamente grato.

Salve, l'autore del post è BigGiu.
Queste tre righe di codice servono a convertire una stringa in un char. LW è una variabile intera.
Si, ho chiesto il vostro aiuto proprio perchè, come spiegato in testa al post, non ottengo l'update di un'immagine ma di un testo.
Non ho mai realizzato nuove classi o eseguito modifiche a librerie esistenti. Un qualsiasi aiuto in questo senso sarebbe gradito.

Purtroppo il discorso della classe ereditata è da scartare perché l'autore ha definito private alcuni dei metodi che sarebbero stati necessari e quindi la tua classe "figlia" non avrebbe accesso a tali metodi.

A questo punto l'opzione del buffer intermedio è quella più "funzionale" e semplice da implementare.
Per curiosità ho provato al volo la libreria con wokwi ed un server FTP pubblico di test (i file vengono cancellati ogni 10 minuti)

L'esempio ovviamente non ha nulla a che vedere con il tuo progetto, sta a te poi estrapolare il meccanismo di base, comprenderlo ed applicarlo al tuo caso.
Ho fatto banalmente copia e incolla con l'esempio incluso nella libreria FTP ed uno spezzone di codice collaudato e testato (proviene da una mia libreria Telegram)

Ti ringrazio, sei molto gentile.
Domani, con calma provvederò a studiare il tuo codice e provare ad applicarlo per le mie necessità.
Spero di poter disturbare di nuovo se incontrerò delle difficoltà.
Buona serata.

@606405: ... non mi sembra di aver visto tuoi post di presentazione, per cui ...

... benvenuto nella sezione Italiana del forum,
cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

Mi scusi ma sono BigGiu ed ho già fatto la mia presentazione.

Ah ... REGOLAMENTO, punto 16.12 ... cortesemente dimmi quale account ti devo bloccare così evitiamo un BAN permanente.

Guglielmo

Scusa, al momento non riesco ad accedere al forum va bloccato 606405.

Grazie e scusami per il disguido.

Va bene, procedo allora con il bloccare 606405, tu prosegui come BigGiu :slight_smile:

Grazie,

Guglielmo