greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.07k stars 503 forks source link

I do not find the created file back in the directory. #287

Closed mstrens closed 3 years ago

mstrens commented 3 years ago

I am using ESP32 with Arduino IDE. I installed SDFat 2.0.6 In a web server on ESP32, I try to upload a file on the SD card attached to the ESP32. The webserver process in 3 steps (controlled by a status): opening the file on SD card, writing each block of data, closing the file. When the code is executed, I can't find an entry in the directory for the new file even if it reports (in the web page) the right number of written bytes. To debug this issue, I added some Serial.print() in the code to trace the execution and then I can see that the program goes into each of the 3 sections without errors. I do not understand why the file does not apear in a dir list.

Note :In other sections of the program, I try to read the list of file in a dir and to read the content of some files. This part is just running fine.

Note: In a previous version, I was using SdFat version 1.0.? and the code was working fine. For running the new version, I just changed SdFat sd; File UploadFile;

by SdFat32 sd; File32 UploadFile;

Could it be that calling the function checkSd() between each step would be the reason for the issue (not finding new created file)?

Here an extract of the (new) code: `

include "SdFat.h"

SdFat32 sd; File32 UploadFile; .......... boolean errorWhileUploading ; void handleFileUpload(){ // upload a new file to the Filing system if (checkSd() ) { HTTPUpload& uploadfile = server.upload(); if(uploadfile.status == UPLOAD_FILE_START) { errorWhileUploading = false ; String filename = uploadfile.filename; sd.remove(filename.c_str()); // Remove a previous version, otherwise data is appended the file again UploadFile.close() ; UploadFile = sd.open(filename.c_str() , O_WRITE | O_CREAT); // Open the file for writing (create it, if doesn't exist) if ( ! UploadFile ) errorWhileUploading = true ; } else if (uploadfile.status == UPLOAD_FILE_WRITE) { if(UploadFile) { int32_t bytesWritten = UploadFile.write(uploadfile.buf, uploadfile.currentSize); // Write the received bytes to the file if ( bytesWritten == -1) errorWhileUploading = true ; } else {
errorWhileUploading = true ; } } else if (uploadfile.status == UPLOAD_FILE_END) { if(UploadFile && ( errorWhileUploading == false) ) // If the file was successfully created {
UploadFile.close(); // Close the file at the end webpage = ""; append_page_header(); webpage += F("

File was successfully uploaded

"); webpage += F("

Uploaded File Name: "); webpage += uploadfile.filename+"

"; webpage += F("

File Size: "); webpage += file_size(uploadfile.totalSize) + "


"; append_page_footer(); server.send(200,"text/html",webpage); Serial.println("file closed without error"); } else { UploadFile.close(); // close for safety ; not sure it is really needed reportError("

Could Not Create Uploaded File (write-protected?)

"); } } }
}

boolean checkSd() { if ( ! sd.begin(SD_CHIPSELECT_PIN , SD_SCK_MHZ(5)) ) {
return false; } if ( ! sd.exists( "/" ) ) { // check if root exist return false; } return true ; }

`

mstrens commented 3 years ago

I just made a new test where I avoided to call checkSd() at each step and now I find the new file in the dir. This solved the issue.

So, I presume that with version 2.0.6 (instead of 1.0.?), I may not call sd.begin() between open() and close(). I did it because I expected that it was a good way to detect if SD card had been removed. The socket that I use does not have a contact to detect insertion/removal of SD card.

Still it is very strange that the functions open, write, close does not report any error in case sd.begin() is called in between.

greiman commented 3 years ago

You could never safely call sd.begin() with a file open. sd.begin() resets the SD and any data in the cache is lost. It likely will corrupt the filesystem.

You can't remove an SD with a file open and expect the SD or file will not be corrupted.

This has been true since 2008 when the first version of SdFat in the Arduino SD.h wrapper was written.

mstrens commented 3 years ago

Thanks for your fast reply.

What is the best way to check if the Sd card is still present? Perhaps using sd.exists( "/" )

What is the best/easiest way to check if a Sd card has been replaced by another one?

greiman commented 3 years ago

There is no sure way using an SdFat function call since the directory entry for the file you check may be in the cache.

The best way is to use an SD module with a card detect pin. All SD sockets have a card detect switch but many Arduino modules don't have a CD pin. Here is an example with CD.

mstrens commented 3 years ago

Indeed, my SD socket is part of a TFT and there is no CD pin.

So, I will have to accept that I can't detect that a SD card has been removed/replaced.

Thanks again.