I've got an Arduino Uno and an Ethernet Shield with imbedded SD card, and am able to successfully serve images and videos from the card to a client browser. But when I load my full website to the card, it only partially launches the site, apparently stalling on some javascript (.js files) imbedded in subdirectories.
My site, as loaded in the SD card, contains the following files in the root directory:
feed.xml
Home_files(folder)
Home.htm
Images(folder)
index.htm
Music_and_Videos_files(folder)
Music_and_Videos.html
Projects_files(folder)
Projects.html
Scripts(folder)
The code I'm using is largely from Ladyada's tutorial, modified to include additional MIME types as follows:
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
/************ ETHERNET STUFF ************/
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 177 };
char rootFileName[] = "index.htm";
Server server(80);
/************ SDCARD STUFF ************/
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
PgmPrint("error: ");
SerialPrintln_P(str);
if (card.errorCode()) {
PgmPrint("SD error: ");
Serial.print(card.errorCode(), HEX);
Serial.print(',');
Serial.println(card.errorData(), HEX);
}
while(1);
}
void setup() {
Serial.begin(115200);
PgmPrint("Free RAM: ");
Serial.println(FreeRam());
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
// breadboards. use SPI_FULL_SPEED for better performance.
pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
digitalWrite(10, HIGH); // but turn off the W5100 chip!
if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
// initialize a FAT volume
if (!volume.init(&card)) error("vol.init failed!");
PgmPrint("Volume is FAT");
Serial.println(volume.fatType(),DEC);
Serial.println();
if (!root.openRoot(&volume)) error("openRoot failed");
// list file in root with date and size
PgmPrintln("Files found in root:");
root.ls(LS_DATE | LS_SIZE);
Serial.println();
// Recursive list of all directories
PgmPrintln("Files found in all dirs:");
root.ls(LS_R);
Serial.println();
PgmPrintln("Done");
// Debugging complete, we start the server!
Ethernet.begin(mac, ip);
server.begin();
}
// How big our line buffer should be. 100 is plenty!
#define BUFSIZ 100
void loop()
{
char clientline[BUFSIZ];
char *filename;
int index = 0;
int image = 0;
Client client = server.available();
if (client) {
// an http request ends with a blank line
boolean current_line_is_blank = true;
// reset the input buffer
index = 0;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// If it isn't a new line, add the character to the buffer
if (c != '\n' && c != '\r') {
clientline[index] = c;
index++;
// are we too big for the buffer? start tossing out data
if (index >= BUFSIZ)
index = BUFSIZ -1;
// continue to read more data!
continue;
}
// got a \n or \r new line, which means the string is done
clientline[index] = 0;
filename = 0;
// Print it out for debugging
Serial.println(clientline);
// Look for substring such as a request to get the root file
if (strstr(clientline, "GET / ") != 0) {
filename = rootFileName;
}
if (strstr(clientline, "GET /") != 0) {
// this time no space after the /, so a sub-file
if (!filename) filename = clientline + 5; // look after the "GET /" (5 chars)
// a little trick, look for the " HTTP/1.1" string and
// turn the first character of the substring into a 0 to clear it out.
(strstr(clientline, " HTTP"))[0] = 0;
// print the file we want
Serial.println(filename);
if (! file.open(&root, filename, O_READ)) {
client.println("HTTP/1.1 404 Not Found");
client.println("Content-Type: text/html");
client.println();
client.println("<h2>File Not Found!</h2>");
break;
}
Serial.println("Opened!");
client.println("HTTP/1.1 200 OK");
if (strstr(filename, ".htm") != 0)
client.println("Content-Type: text/html");
else if (strstr(filename, ".css") != 0)
client.println("Content-Type: text/css");
else if (strstr(filename, ".png") != 0)
client.println("Content-Type: image/png");
else if (strstr(filename, ".jpg") != 0)
client.println("Content-Type: image/jpeg");
else if (strstr(filename, ".gif") != 0)
client.println("Content-Type: image/gif");
else if (strstr(filename, ".3gp") != 0)
client.println("Content-Type: video/mpeg");
else if (strstr(filename, ".pdf") != 0)
client.println("Content-Type: application/pdf");
else if (strstr(filename, ".js") != 0)
client.println("Content-Type: application/x-javascript");
else if (strstr(filename, ".xml") != 0)
client.println("Content-Type: application/xml");
else
client.println("Content-Type: text");
client.println();
int16_t c;
while ((c = file.read()) >= 0) {
// uncomment the serial to debug (slow!)
//Serial.print((char)c);
client.print((char)c);
}
file.close();
} else {
// everything else is a 404
client.println("HTTP/1.1 404 Not Found");
client.println("Content-Type: text/html");
client.println();
client.println("<h2>File Not Found!</h2>");
}
break;
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
}
}
Note that, in order to get my site to launch at all, I changed names of 2 files to fit DOS 8.3 format; in particular, I renamed index.html to index.htm, Home.html to Home.htm, and then I modified the index.htm file to call Home.htm rather than Home.html as it originally did. So I'm thinking the 8.3 format issue is hitting me elsewhere in the file chain.
The serial monitor window shows the following activity, initiated when I enter
http://192.168.1.177 into any browser:
GET / HTTP/1.1
index.htm
Opened!
GET /Home.htm HTTP/1.1
Home.htm
Opened!
GET /Scripts/iWebSite.js HTTP/1.1
Scripts/iWebSite.js
GET /Scripts/Widgets/SharedResources/WidgetCommon.js HTTP/1.1
Scripts/Widgets/SharedResources/WidgetCommon.js
GET /Scripts/Widgets/Navbar/navbar.js HTTP/1.1
Scripts/Widgets/Navbar/navbar.js
GET /Home_files/Home.js HTTP/1.1
Home_files/Home.js
GET /Home_files/about_me.png HTTP/1.1
Home_files/about_me.png
GET /Home_files/Home.css HTTP/1.1
Home_files/Home.css
GET /Home_files/shapeimage_4.png HTTP/1.1
Home_files/shapeimage_4.png
GET /Home_files/shapeimage_3.png HTTP/1.1
Home_files/shapeimage_3.png
GET /Home_files/shapeimage_1.png HTTP/1.1
Home_files/shapeimage_1.png
GET /Home_files/shapeimage_2.png HTTP/1.1
Home_files/shapeimage_2.png
I suspect my error is obvious to someone out there. Can anybody help?