String
getContentType(
String
filename) {
// convert the file extension to the MIME type
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
(
".ico"
))
return
"image/x-icon"
;
return
"text/plain"
;
}
bool
handleFileRead(
String
path) {
// send the right file to the client (if it exists)
Serial
.
println
(
"handleFileRead: "
+
path);
if
(path
.
endsWith
(
"/"
)) path
+=
"index.html"
;
// If a folder is requested, send the index file
String
contentType
=
getContentType(path);
// Get the MIME type
if
(SPIFFS
.
exists
(path)) {
// If the file exists
File
file
=
SPIFFS
.
open
(path
,
"r"
);
// Open it
size_t
sent
=
server
.
streamFile(file
,
contentType);
// And send it to the client
file
.
close
();
// Then close the file again
return
true
;
}
Serial
.
println
(
"\tFile Not Found"
);
return
false
;
// If the file doesn't exist, return false
}
As you can see, we don't use
server.on
in this example. Instead, we use
server.onNotFound
: this will match any URI, since we didn't
declare any specific URI handlers like in the previous server examples.
When a URI is requested, we call the function
handleFileRead
. This function checks if the URI of the HTTP request is the path to an
existing file in the SPIFFS. If that's the case, it sends the file back to the client. If the path doesn't exist, it returns false, and a 404 (Not
Found) HTTP status will be sent.
The MIME type for the different files is based on the file extension.
You could add other file types as well. For instance:
String
getContentType(
String
filename){
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"
;
}
This example is adapted from the FSBrowser example by Hristo Gochkov.
Compressing files
The ESP8266's flash memory isn't huge, and most text files, like html, css etc. can be compressed by quite a large factor. Modern web
browsers accept compressed files as a response, so we'll take advantage of this by uploading compressed versions of our html and
icon files to the SPIFFS, in order to save space and bandwidth.
To do this, we need to add the GNU zip file type to our list of MIME types:
String
getContentType(
String
filename){
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
(
".ico"
))
return
"image/x-icon"
;
else
if
(filename
.
endsWith
(
".gz"
))
return
"application/x-gzip"
;
return
"text/plain"
;
}
And we need to change our
handleFileRead
function as well:
bool
handleFileRead(
String
path){
// send the right file to the client (if it exists)
Serial
.
println
(
"handleFileRead: "
+
path);
if
(path
.
endsWith
(
"/"
)) path
+=
"index.html"
;
// If a folder is requested, send the index file
String
contentType
=
getContentType(path);
// Get the MIME type
String
pathWithGz
=
path
+
".gz"
;
if
(SPIFFS
.
exists
(pathWithGz)
||
SPIFFS
.
exists
(path)){
// If the file exists, either as a compressed archive, or normal
if
(SPIFFS
.
exists
(pathWithGz))
// If there's a compressed version available
path
+=
".gz"
;
// Use the compressed version
File
file
=
SPIFFS
.
open
(path
,
"r"
);
// Open the file
size_t
sent
=
server
.
streamFile(file
,
contentType);
// Send it to the client
file
.
close
();
// Close the file again
Serial
.
println
(
String
(
"\tSent file: "
)
+
path);
return
true
;
}
Serial
.
println
(
String
(
"\tFile Not Found: "
)
+
path);
return
false
;
// If the file doesn't exist, return false
}
Now, try compressing some of the files to the GNU zip format (.gz), and uploading them to SPIFFS. Or you can just download the new
data folder (unzip it first).
Every time a client requests a certain file, the ESP will check if a compressed version is available. If so, it will use that instead of the
uncompressed file. The output in the Serial Monitor should look something like this:
handleFileRead: /
Sent file: /index.html.gz
handleFileRead: /main.css
Sent file: /main.css
handleFileRead: /JavaScript.js
Sent file: /JavaScript.js
handleFileRead: /folder/JavaScript.js
Sent file: /folder/JavaScript.js
handleFileRead: /favicon.ico
Sent file: /favicon.ico.gz