Bonjour,
j'ai une fonction sur un ESP32-S3 qui télécharge un fichier a partir d'une Url et l'enregistre une carte SD (configurée en SPI)
le souci que j'ai, c'est que l'écriture du fichier sur la carte SD est "aléatoire". Parfois le fichier fait la bonne taille, parfois (plutot souvent ^^) le fichier est tronqué. Dans le cas d'un MP3, le fichier tronqué n'est pas corrompu, il est lisible mais coupe avant la fin prévue.
voici la fonction :
void download(String url, File file)
{
HTTPClient http;
int temp_ = millis();
http.begin(url);
http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
// Entêtes spécifiques
http.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
http.addHeader("Accept", "audio/*, */*;q=0.8");
http.addHeader("Connection", "close");
int httpcode = http.GET();
if (httpcode <= 0) {
Serial.println("[HTTP] GET failed");
Serial.print("Error code: ");
Serial.println(httpcode);
http.end();
return;
}
int file_size = http.getSize();
Serial.print("Size : ");
Serial.println(file_size);
WiFiClient* stream = http.getStreamPtr();
static uint8_t buff[128];
int len = file_size;
float full = 0;
unsigned long lastProgressUpdate = millis();
unsigned long startTime = millis();
Serial.println("Starting download...");
Serial.print("Expected size: ");
Serial.print(file_size / 1000000.0, 2);
Serial.println(" MB");
while (http.connected() && (len > 0 || len == -1)) {
size_t size = stream->available();
if (size > 0) {
//int toRead = min(size, sizeof(buff));
int c = stream->readBytes((char*)buff, sizeof(buff));
if (c > 0) {
file.write(buff, c);
full += c;
if (millis() - lastProgressUpdate > 1000) {
Serial.print("Downloaded: ");
Serial.print(full / 1000000, 1);
Serial.println(" MB");
lastProgressUpdate = millis();
}
if (len > 0) len -= c;
/* // Reset du watchdog toutes les 5 secondes
if (millis() - startTime > 5000) {
yield(); // Permet au système de reset le watchdog
}*/
}
} else {
delay(2);
}
}
file.flush();
http.end();
int temp2 = millis();
int diff = (temp2 - temp_) / 1000;
Serial.println("Download finished");
Serial.print("Diff : ");
Serial.println(diff);
// Vérification finale
if (file_size > 0 && file.size() != file_size) {
Serial.println("WARNING: File size mismatch!");
Serial.print("Expected: "); Serial.print(file_size);
Serial.print(", Got: "); Serial.println(file.size());
} else if (file_size > 0) {
Serial.println("Download completed successfully!");
}
}
Il y a un coté aléatoire, voici par exemple le retour sur le Serial de 3 téléchargement du meme fichier à la suite :
/Quand l'impossible devient possible, à quand le déclic - .mp3Size : 4836347
Starting download...
Expected size: 4.84 MB
Downloaded: 0.6 MB
Downloaded: 1.3 MB
Downloaded: 2.0 MB
Downloaded: 2.7 MB
Downloaded: 3.4 MB
Downloaded: 4.1 MB
Download finished
Diff : 8
WARNING: File size mismatch!
Expected: 4836347, Got: 4583424
/Quand l'impossible devient possible, à quand le déclic - .mp3Size : 4836347
Starting download...
Expected size: 4.84 MB
Downloaded: 0.6 MB
Downloaded: 1.5 MB
Downloaded: 2.4 MB
Downloaded: 3.2 MB
Downloaded: 4.0 MB
Download finished
Diff : 6
WARNING: File size mismatch!
Expected: 4836347, Got: 335872
/Quand l'impossible devient possible, à quand le déclic - .mp3Size : 4836347
Starting download...
Expected size: 4.84 MB
Downloaded: 0.6 MB
Downloaded: 1.2 MB
Downloaded: 2.0 MB
Downloaded: 2.9 MB
Downloaded: 3.7 MB
Downloaded: 4.6 MB
Download finished
Diff : 7
WARNING: File size mismatch!
Expected: 4836347, Got: 1097728
/Quand l'impossible devient possible, à quand le déclic - .mp3Size : 4836347
Starting download...
Expected size: 4.84 MB
Downloaded: 0.6 MB
Downloaded: 1.1 MB
Downloaded: 1.7 MB
Downloaded: 2.3 MB
Downloaded: 2.8 MB
Downloaded: 3.4 MB
Downloaded: 3.8 MB
Downloaded: 4.3 MB
Download finished
Diff : 9
Download completed successfully!
Le comportement typique d'un téléchargement qui n'abouti pas c'est une vitesse constante, et on observe soudainement une brusque augmentation de la vitesse de téléchargement. La taille finale du fichier correspond au moment du basculement entre les 2 vitesses.
Ce que j'ai testé :
- Jouer sur la taille du buffer : Je suis allé du très petite (64) au très gros (16384). Pour le moment la taille qui a eu le plus téléchargement correcte semble etre 128
- jouer sur la vitesse du port SPI (de 4 a 80 Mhz) mis a part jouer sur la vitesse de téléchargement, je n'ai pas remarqué d'effet sur le succès ou non du téléchargement
- appeler régulièrement un .flush() dans la boucle pour forcer l'écriture
- j'ai rapidement testé la fonction : http.writeToStream(&file); qui doit gérer la taille du buffer de façon automatique et éviter les erreur. Résutlat : Même sur les petits fichier, ça n'abouti par, la taille finale du fichier varie de façon aléatoire.
La seule tendance que j'observe que quand une combinaison de tout ça semble fonctionner, les fichiers de qlq Mo
ce qui ne n'ai pas testé :
- des requettes en httpS
Si quelqu'un a une idée de l'origine du problème, je suis preneur. Merci !