ESP32 WebServer Library – sendContent_P()

Home / References / ESP32 Library / WebServer Library

Description

The sendContent_P() method is a powerful function in the ESP32 WebServer Library designed to send content stored in PROGMEM (program memory) to a client as part of an HTTP response. This method is particularly useful for serving static content, such as HTML, CSS, or JavaScript, efficiently by leveraging the ESP32’s flash memory, reducing RAM usage. It is ideal for projects where memory optimization is key, allowing makers to deliver web content seamlessly.


Syntax and Usage

The sendContent_P() method can be used in two distinct ways depending on whether you need to specify the content length explicitly. Below are the available syntaxes:

  • Without Length Argument: Sends PROGMEM content without specifying its size, relying on the method to determine the length automatically using strlen_P().
  • With Length Argument: Sends PROGMEM content with an explicitly defined size, giving you precise control over the data being transmitted.

Here’s how to use it in code:

void sendContent_P(PGM_P content);
void sendContent_P(PGM_P content, size_t size);

For practical applications and examples of this method, please consult the “Example Code” section on this page. This section provides comprehensive guidance to help you better understand and apply the method effectively.


Argument(s)

  • content (PGM_P): A pointer to the data stored in PROGMEM. This argument specifies the content to be sent to the client. It must be defined using the PROGMEM keyword to ensure it resides in flash memory.
  • size (size_t, optional): The length of the content in bytes. This argument is used only in the second syntax variant to explicitly define how many bytes of the PROGMEM content should be sent. If omitted, the method calculates the length automatically.

Return Value

The sendContent_P() method does not return a value. It directly writes the specified PROGMEM content to the current client connection as part of the HTTP response. If the operation fails (e.g., due to a disconnected client), it will silently terminate without throwing an error, as it operates within the WebServer’s client handling context.


Example Codes

Example: Using sendContent_P() Without Length Argument

This code demonstrates how to use the ESP32 WebServer Library’s sendContent_P() method to serve HTML content stored in PROGMEM. This technique helps to conserve RAM on the ESP32 by storing static HTML content in flash memory.

To use this code, replace “your-SSID” and “your-PASSWORD” with your Wi-Fi credentials. After uploading the code to your ESP32, open the Serial Monitor to find the ESP32’s IP address. Then, open a web browser and navigate to that IP address to view the HTML content served from PROGMEM.

/*
 * Author: Avant Maker
 * Date: March 17, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use ESP32 WebServer Library's 
 * sendContent_P() method to server HTML content stored in PROGMEM,
 * which helps conserve RAM on your ESP32 device.
 *
 * Code Source:
 * This example code is sourced from the Comprehensive Guide
 * to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
 * For additional code examples and in-depth documentation related to
 * the ESP32 Arduino Core Library, please visit:
 *
 * https://avantmaker.com/home/all-about-esp32-arduino-core-library/
 *
 * AvantMaker.com, your premier destination for all things
 * DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
 * to empowering makers, learners, and enthusiasts with
 * the resources they need to bring their innovative ideas to life.
 */
/*
  ESP32 WebServer sendContent_P Example
  
  This sketch demonstrates how to use the sendContent_P method of the ESP32 WebServer
  library to serve web content stored in program memory (PROGMEM). This approach
  helps conserve RAM when serving larger static content like HTML pages.

  Created for AvantMaker.com
*/

#include <WiFi.h>
#include <WebServer.h>

// Network credentials
const char* ssid = "your_SSID";          // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD";  // Replace with your Wi-Fi password

// Web server on port 80
WebServer server(80);

// HTML content stored in program memory (PROGMEM)
// This helps to save RAM as the HTML is stored in flash memory instead
const char MAIN_page[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ESP32 PROGMEM Content Example</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
      background-color: #f8f9fa;
      color: #333;
    }
    .container {
      max-width: 800px;
      margin: 0 auto;
      background-color: white;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    }
    h1 {
      color: #0066cc;
      text-align: center;
    }
    .section {
      margin-bottom: 20px;
      padding: 15px;
      background-color: #e9f7fe;
      border-radius: 5px;
    }
    .footer {
      text-align: center;
      margin-top: 30px;
      font-size: 0.8em;
      color: #666;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>AvantMaker ESP32 WebServer sendContent_P Demo</h1>
    
    <div class="section">
      <h2>About This Example</h2>
      <p>This page demonstrates how the ESP32 WebServer library's <code>sendContent_P</code> method works.
         The entire HTML content is stored in PROGMEM (program memory) rather than RAM, which is
         especially important when serving larger web pages.</p>
    </div>
    
    <div class="section">
      <h2>Benefits of Using PROGMEM</h2>
      <ul>
        <li>Conserves precious RAM</li>
        <li>Allows serving larger web pages</li>
        <li>No need to allocate dynamic memory for content</li>
        <li>More stable operation with less chance of memory fragmentation</li>
      </ul>
    </div>
    
    <div class="section">
      <h2>ESP32 Status</h2>
      <p>WiFi SSID: %SSID%</p>
      <p>IP Address: %IP%</p>
      <p>Free Heap: %HEAP% bytes</p>
      <p>Uptime: %UPTIME% seconds</p>
    </div>
    
    <div class="footer">
      <p>Created for AvantMaker.com - Your Premier Hub for DIY, AI, IoT, and STEM Innovation</p>
    </div>
  </div>
</body>
</html>
)rawliteral";

// Function to handle root path
void handleRoot() {
  String html = FPSTR(MAIN_page); // Convert PROGMEM content to String
  
  // Replace placeholders with dynamic values
  html.replace("%SSID%", String(ssid));
  html.replace("%IP%", WiFi.localIP().toString());
  html.replace("%HEAP%", String(ESP.getFreeHeap()));
  html.replace("%UPTIME%", String(millis() / 1000));
  
  // Set content type
  server.setContentLength(html.length());
  server.send(200, "text/html", ""); // Send the header but no content yet
  
  // Send content in chunks using sendContent_P
  // For demonstration, we'll split the content into chunks of 1024 bytes
  const int chunkSize = 1024;
  for (size_t i = 0; i < html.length(); i += chunkSize) {
    // Calculate the size of this chunk
    size_t currentChunkSize = html.length() - i;
    if (currentChunkSize > chunkSize) {
      currentChunkSize = chunkSize;
    }
    
    // Create a temporary buffer for this chunk
    char chunk[chunkSize + 1];
    html.substring(i, i + currentChunkSize).toCharArray(chunk, currentChunkSize + 1);
    
    // Send the chunk
    server.sendContent(chunk);
  }
}

// Alternative function showcasing direct use of sendContent_P with PROGMEM data
void handleDirectPROGMEM() {
  // Set content type
  server.send(200, "text/html", ""); // Send only headers
  
  // Send content directly from PROGMEM
  // This method sends the entire content at once
  server.sendContent_P(MAIN_page);
}

// Function to handle 404 Not Found
void handleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  
  server.send(404, "text/plain", message);
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  // Connect to Wi-Fi
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  // Print connection details
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  // Setup server routes
  server.on("/", handleRoot);
  server.on("/direct", handleDirectPROGMEM); // Alternative route showing direct PROGMEM usage
  server.onNotFound(handleNotFound);
  
  // Start server
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
  // Add any additional background processing here
}
error: Content is protected !!