I am trying to download a file from an ESP32 which is running the PsychicHTTP webserver. For testing, this is just a fixed .CSV file. In HTML:
<div>
<button type="button" onclick="saveFile()">Save file</button>
</div>
In the associated Javascript:
function saveFile() {
var xhr = new XMLHttpRequest();
console.log("SAVING FILE");
xhr.open("GET", "/saveFile", true);
xhr.send();
}
In the ESP32 code, in the setup for the webserver:
server.on("/saveFile", [](PsychicRequest *request) {
Serial.println("SAVE FILE REQUEST");
String filename = "/results/sample.csv";
PsychicFileResponse response(request, LittleFS, filename, (String&)("text/csv"), true);
return response.send();
});
I have also made a small mod to the PsychicHTTP webserver code to include “text/csv” as a MIME type.
When this is all running, the webserver receives the GET request for the download, I can see this in the Firefox console and in the ESP32 serial message. However the file doesn’t download. ESP32 is at 192.168.0.136 so if I type in 192.168.0.136/saveFile directly in the browser address bar then the file is downloaded and saved.
I have seen a few different examples of file downloads in Javascript and they all seem to use either “FETCH” or some form of HTML. Something like this:
function downloadFile(url, fileName) {
fetch(url, { method: 'get', mode: 'no-cors', referrerPolicy: 'no-referrer' })
.then(res => res.blob())
.then(res => {
const aElement = document.createElement('a');
aElement.setAttribute('download', fileName);
const href = URL.createObjectURL(res);
aElement.href = href;
aElement.setAttribute('target', '_blank');
aElement.click();
URL.revokeObjectURL(href);
});
};
I can also try the simple HTML version of this when I get time – just using tag with download attribute – as my requirement is pretty simple.
So my two questions:
- Why does a direct addressing to the download link work from the address bar but the Javascript above does not work?
- If I use the FETCH example below, do I retain the same code in the ESP32 to respond or is something different required?