简体   繁体   中英

How can I make a web server with arduino that support multiple file?

I am wondering how I can make a http server for arduino however the problem I am encountering is that I don't understand how I can server static html file on it. All of the tutorial I looked on it loaded the html directly through the code like like this:

/*
  Web Server

 A simple web server that shows the value of the analog input pins.
 using an Arduino Wiznet Ethernet shield.

 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Analog inputs attached to pins A0 through A5 (optional)

 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 modified 02 Sept 2015
 by Arturo Guadalupi
 
 */

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
  // You can use Ethernet.init(pin) to configure the CS pin
  //Ethernet.init(10);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Ethernet WebServer Example");

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start the server
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("<br />");
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}

The code cause a problem where you can't sideload images without being stored on a another server. In fact, I wish I could load multiple file from a storage medium like a sd card where I could use <script src="app.js></script> tags to load content from an location on the sdcard.

One of the solution I tough of, would be to use the SD card arduino library. However, it cause me a problem as I am unsure if I can load the stylesheet, scripts and others resources that are located in the sdcard from a html file located from the web page( <img src="logo.jpg alt="logo /> . I tough of making that with loading the webpage through the file located in the sdcard.

You don't have to decide on the server side (the Arduino) which files to send; the webbrowser itself will send a GET for every image, script, stylesheet, etc. it comes across in an HTML page and wants to have.

All the server has to do is respond to each ot those GET s with the right file, and all the separate files have to be present in the Arduino's memory, or on external storage like an SD card.

A shortcut you can take is making self-contained web pages, that contain all images, scripts, and stylesheets in one file, like I did here . It's a pain to do, but it simplifies the webserver code, as there is only one file to serve, and its content can be put in a variable in the code if the memory of the Arduino you use is large enough.

If you don't care about writing your own webserver, you could use a webserver library, and put the files you need on an SD card. The webserver as implemented in the library will respond to every GET the browser sends with the right file, and that's that.

If this doesn't answer your question, let me know, and I'll edit or expand.

PS. I put an example of how to serve a self-contained web page, that was gzipped and Base64-encoded, and then put into the Arduino code as a const char* variable, on Github. The actual gzipped, Base64-encoded web page is here , the webserver part of the code is here , the function to send a gzipped, Base64-encoded web page to the browser is here .

To serve files from a webserver you have to look at the HTTP request headers to see what file is requested.

You should already be able to see those headers in the serial monitor since you're using:

    char c = client.read();
    Serial.write(c);

The first line from a GET request looks like:

GET /test.html HTTP/1.1

Or just:

GET / HTTP/1.1

where you would normally return index.html.

So here you can just return the contents of test.html (from memory or SD card for example).

If your test.html file contains references to other files (eg logo.jpg), the browser will automatically send a new GET request for logo.jpg (followed by other header fields):

GET /logo.jpg HTTP/1.1

You also have to adjust the Content-Type response header field:

Content-Type: image/jpeg

The length of the file (or data) should be included in the response headers, for example:

Content-Length: 520

Alternatively chunked transfer encoding can be used (mostly for dynamic content where the total size is not known up front).

Sorry I don't have any specific answer for you. But taking a look here or another example program on the web should help.

Though I think I'd pick the Raspberry Pi for an embedded webserver due to it's having an operating system.

You can use the library awot. It's basically express js for arduino which mean you can do a restful api easily. On the website of awot they have tutorial on how to deploy a react app on a arduino on the website of awot.

Here's the link of awot: https://awot.net/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM