一、代码

ESP32 IDF框架的网页服务器,包含WiFi连接(AP+STA)、HTTP服务、前端交互和硬件控制功能:

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_http_server.h"
#include "driver/gpio.h"
#include "cJSON.h"

// WiFi配置
#define WIFI_SSID      "adb"
#define WIFI_PASS      "abc@0102"
#define LED_GPIO       GPIO_NUM_2  // 板载LED引脚

// 全局变量
static const char *TAG = "WEB_SERVER";
static httpd_handle_t server = NULL;
static bool led_state = false;

// WiFi连接初始化
static void wifi_init_sta(void) {
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK
        },
    };

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_LOGI(TAG, "WiFi初始化完成,正在连接AP...");
}

// 事件处理
static int s_retry_num = 0;
// 事件处理
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data) 
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) 
    {
        esp_wifi_connect();
    } 
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) 
    {
        if (s_retry_num < 6) 
        {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        } 
        else 
        {
            ESP_LOGI(TAG,"connect to the AP fail");
        }
        
    } 
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) 
    {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "获得IP地址: " IPSTR, IP2STR(&event->ip_info.ip));
        start_webserver();
        s_retry_num=0;
    }
}

// HTTP请求处理函数
static esp_err_t root_get_handler(httpd_req_t *req) {
    extern const char index_html_start[] asm("_binary_index_html_start");
    extern const char index_html_end[] asm("_binary_index_html_end");

    extern const unsigned int len2  asm ("index_html_length");

    printf("len2=%d\n",len2);
    printf("len=%d\n",index_html_end-index_html_start);
    printf("strlen(index_html_start)=%d\n",strlen(index_html_start));
    httpd_resp_set_type(req, "text/html");
    //strlen(index_html_start) 获取的长度比实际的多2个字节
    httpd_resp_send(req, index_html_start, len2);
    return ESP_OK;
}


static esp_err_t led_post_handler(httpd_req_t *req) {
    char buf[10];
    int ret = httpd_req_recv(req, buf, sizeof(buf));
    
    if (ret > 0) {
        buf[ret] = '\0';
        if (strcmp(buf, "toggle") == 0) {
            led_state = !led_state;
            gpio_set_level(LED_GPIO, led_state);
            httpd_resp_sendstr(req, led_state ? "ON" : "OFF");
        }
    }
    return ESP_OK;
}

static esp_err_t sensor_get_handler(httpd_req_t *req) {
    // 模拟传感器数据(实际项目应替换为真实传感器读取)
    cJSON *root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "temperature", 25.6);
    cJSON_AddNumberToObject(root, "humidity", 65.2);
    
    const char *json_str = cJSON_PrintUnformatted(root);
    httpd_resp_set_type(req, "application/json");
    httpd_resp_sendstr(req, json_str);
    
    cJSON_Delete(root);
    free((void*)json_str);
    return ESP_OK;
}

// 启动Web服务器
void start_webserver() {
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.max_uri_handlers = 8;

    // 注册URI处理器
    httpd_uri_t uri_get = {
        .uri = "/",
        .method = HTTP_GET,
        .handler = root_get_handler,
        .user_ctx = NULL
    };

    httpd_uri_t uri_led = {
        .uri = "/led",
        .method = HTTP_POST,
        .handler = led_post_handler,
        .user_ctx = NULL
    };

    httpd_uri_t uri_sensor = {
        .uri = "/sensor",
        .method = HTTP_GET,
        .handler = sensor_get_handler,
        .user_ctx = NULL
    };

    if (httpd_start(&server, &config) == ESP_OK) {
        httpd_register_uri_handler(server, &uri_get);
        httpd_register_uri_handler(server, &uri_led);
        httpd_register_uri_handler(server, &uri_sensor);
        ESP_LOGI(TAG, "HTTP服务器启动成功");
    }
}

void app_main(void) {
    // 初始化NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // 初始化GPIO
    gpio_reset_pin(LED_GPIO);
    gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);

    // 初始化网络
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    // 注册事件处理器
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));

    // 启动WiFi
    wifi_init_sta();
}

 二、配套HTML文件 (index.html)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ESP32控制面板</title>
    <style>
        body { font-family: Arial; text-align: center; margin: 40px; }
        .btn { 
            padding: 15px 30px; 
            font-size: 18px; 
            background: #4CAF50; 
            color: white; 
            border: none; 
            border-radius: 5px; 
            cursor: pointer;
        }
        .status { margin-top: 20px; font-size: 20px; }
    </style>
</head>
<body>
    <h1>ESP32控制面板</h1>
    <button class="btn" onclick="toggleLED()">切换LED状态</button>
    <div class="status">
        <p>传感器数据: <span id="sensorData">加载中...</span></p>
    </div>

    <script>
        function toggleLED() {
            fetch('/led', { 
                method: 'POST',
                body: 'toggle'
            })
            .then(response => response.text())
            .then(state => {
                alert('当前LED状态: ' + state);
            });
        }

        // 每2秒更新传感器数据
        setInterval(() => {
            fetch('/sensor')
                .then(response => response.json())
                .then(data => {
                    document.getElementById('sensorData').innerHTML = 
                        `${data.temperature}℃ / ${data.humidity}%`;
                });
        }, 2000);
    </script>
</body>
</html>

三、工程结构

my_web_server/
├── CMakeLists.txt
├── main/
│   ├── CMakeLists.txt
│   └── main.c         # 上述C代码
└── components/
    └── web_files/
        └── index.html  # 上述HTML文件

四、功能说明
1、硬件控制:通过GPIO2控制板载LED
2、数据接口:
GET /:返回控制页面
POST /led:切换LED状态
GET /sensor:获取模拟传感器数据
3、前端功能:
实时显示传感器数据(每2秒更新)
按钮控制LED状态
响应式界面设计

4、测试验证

  • 查看串口输出的IP地址
  • 浏览器访问 http://[ESP32_IP]/
  • 点击按钮测试LED控制
  • 观察传感器数据更新

代码实现了完整的Web服务器功能,如需扩展功能可在此基础上添加更多URI处理逻辑。


<style>
    .menu_button {
        width: 100%;
        height: 50px;
        border-radius: 4px;
        text-align: center;
        cursor: pointer;
        display: block;
        margin-bottom: 5px;
        font: 14px/50px Tahoma;
        transition: all 0.18s ease-in-out;
        border: 1px solid #4FD666;
        background: linear-gradient(to top right, #3EC97A, #69EA49 20%, rgba(255, 255, 255, 0) 80%, rgba(255, 255, 255, 0)) top right/500% 500%;
        color: green;
    }

    .menu_button:hover {
        color: white;
        background-position: bottom left;
    }

    .hidden_input {
        width: 0.1px;
        height: 0.1px;
        opacity: 0;
        overflow: hidden;
        position: absolute;
        z-index: -1;
    }

    .imgBox {
        border: 2px dashed green;
        border-radius: 8px;
        background: lightyellow;
        background-repeat: no-repeat;
        text-align: center;
        margin-top: 10px;
    }

    .mesBox {
        margin: 100px 70px;
        color: green;
        font-size: 25px;
        font-family: Verdana, Arial, sans-serif;
    }

    .header_back {
        width: 100%;
        height: 20px;
        background: #EEEEEE;
    }

    .content_back {
        width: 100%;
        background: #EEEEEE;
    }

    .footer_back {
        width: 100%;
        height: 20px;
        background: #EEEEEE;
    }

    .header_face {
        width: 100%;
        height: 20px;
        margin: 0 auto;
        background: #ebefeb;
    }

    .content_face {
        width: 100%;
        height: 100%;
        margin: 0 auto;
        background: #FFFFFF;
    }

    .footer_face {
        width: 100%;
        height: 100%;
        margin: 0 auto;
        background: #CCFFCC;
    }

    .menu_bar {
        border-right: 1px solid #4FD666;
        background: #EEFFEE;
        vertical-align: top;
        padding: 15px;
        width: 200px;
        height: 100%
    }

    .content_body {
        vertical-align: top;
        text-align: center;
        height: 100%;
        padding: 30px;
        padding-left: 15px;
    }

    .title {
        color: green;
        font-size: 32px;
        font-family: arial;
    }

    .comment {
        width: 100%;
        color: green;
        font-size: 16px;
        font-style: italic;
        font-family: arial;
        text-align: center;
    }

    .nud {
        width: 70px;
    }
</style>


<script type="text/javascript">
    var srcBox, srcImg, dstImg;
    var epdArr, epdInd, palArr;
    var curPal;
    function getElm(n) {
        return document.getElementById(n);
    }

    function setInn(n, i) {
        document.getElementById(n).innerHTML = i;

    }

    function processFiles(files) {
        var file = files[0];
        var reader = new FileReader();
        srcImg = new Image();
        reader.onload = function (e) {
            setInn('srcBox', '<img id="imgView" class="sourceImage">');
            var img = getElm('imgView');
            img.src = e.target.result;
            srcImg.src = e.target.result;
        };
        reader.readAsDataURL(file);
    }

    function drop(e) {
        e.stopPropagation();
        e.preventDefault();
        var files = e.dataTransfer.files;
        processFiles(files);
    }
    function ignoreDrag(e) {
        e.stopPropagation();
        e.preventDefault();
    }
    function getNud(nm, vl) {
        return '<td class="comment">' + nm + ':</td>' +
            '<td><input id="nud_' + nm + '" class="nud"type="number" value="' + vl + '"/></td>';
    }
    function Btn(nm, tx, fn) {
        return '<div><label class="menu_button" for="_' + nm + '">' + tx + '</label>' +
            '<input class="hidden_input" id="_' + nm + '" type="' +
            (nm == 0 ? 'file" onchange="' : 'button" onclick="') + fn + '"/></div>';
    }
    function RB(vl, tx) {
        return '<input type="radio" name="kind" value="m' + vl +
            '" onclick="rbClick(' + vl + ');"' + (vl == 0 ? 'checked="true"' : '') + '/>' + tx;
    }
    window.onload = function () {
        srcBox = getElm('srcBox');
        srcBox.ondragenter = ignoreDrag;
        srcBox.ondragover = ignoreDrag;
        srcBox.ondrop = drop;
        srcImg = 0;
        epdInd = 0;
        palArr = [[[0, 0, 0], [255, 255, 255]],
        [[0, 0, 0], [255, 255, 255], [127, 0, 0]],
        [[0, 0, 0], [255, 255, 255], [127, 127, 127]],
        [[0, 0, 0], [255, 255, 255], [127, 127, 127], [127, 0, 0]],
        [[0, 0, 0], [255, 255, 255]],
        [[0, 0, 0], [255, 255, 255], [220, 180, 0]],
        [[0, 0, 0]],
        [[0, 0, 0], [255, 255, 255], [0, 255, 0], [0, 0, 255], [255, 0, 0], [255, 255, 0], [255, 128, 0]]];
        epdArr = [[200, 200, 0], [200, 200, 3], [152, 152, 5],
        [122, 250, 0], [104, 212, 1], [104, 212, 5], [104, 212, 0],
        [176, 264, 0], [176, 264, 1],
        [128, 296, 0], [128, 296, 1], [128, 296, 5], [128, 296, 0],
        [400, 300, 0], [400, 300, 1], [400, 300, 5],
        [600, 448, 0], [600, 448, 1], [600, 448, 5],
        [640, 384, 0], [640, 384, 1], [640, 384, 5],
        [800, 480, 0], [800, 480, 1], [880, 528, 1],
        [600, 448, 7], [880, 528, 0], [280, 480, 0],
        [152, 296, 0], [648, 480, 1], [128, 296, 1],
        [200, 200, 1], [104, 214, 1], [128, 296, 0],
        [400, 300, 1], [152, 296, 1], [648, 480, 0],
        [640, 400, 7], [176, 264, 1], [122, 250, 0],
        [122, 250, 1], [240, 360, 0], [176, 264, 0],
        [122, 250, 0], [400, 300, 0], [960, 680, 0],
        [800, 480, 0], [128, 296, 1], [960, 680, 1]];
        setInn('BT',
            Btn(0, 'Select image file', 'processFiles(this.files);') +
            Btn(1, 'Level: mono', 'procImg(true,false);') +
            Btn(2, 'Level: color', 'procImg(true,true);') +
            Btn(3, 'Dithering: mono', 'procImg(false,false);') +
            Btn(4, 'Dithering: color', 'procImg(false,true);') +
            Btn(5, 'Upload image', 'uploadImage();'));
        setInn('XY', getNud('x', '0') + getNud('y', '0'));
        setInn('WH', getNud('w', '200') + getNud('h', '200'));
        setInn('RB', RB(0, '1.54 &ensp;') + RB(1, '1.54b') + RB(2, '1.54c&ensp;<br>') +
            RB(3, '2.13&ensp;') + RB(4, '2.13b') + RB(5, '2.13c<br>') +
            RB(6, '2.13d') + RB(7, '2.7&ensp;&ensp;') + RB(8, '2.7b&ensp;<br>') +
            RB(9, '2.9&ensp;&ensp;') + RB(10, '2.9b&ensp;') + RB(11, '2.9c&ensp;<br>') +
            RB(12, '2.9d&ensp;') + RB(13, '4.2&ensp;&ensp;') + RB(14, '4.2b&ensp;<br>') +
            RB(15, '4.2c&ensp;') + RB(16, '5.83&ensp;') + RB(17, '5.83b<br>') +
            RB(18, '5.83c&ensp;') + RB(19, '7.5&ensp;&ensp;') + RB(20, '7.5b<br>') +
            RB(21, '7.5c') + RB(22, '7.5 V2') + RB(23, '7.5b-V2<br>') +
            RB(24, '7.5b HD&ensp;') + RB(25, '5.65f<br>') +
            RB(26, '7.5 HD&ensp;') + RB(27, '3.7&ensp;') + RB(28, '2.66<br>') +
            RB(29, '5.83b V2&ensp;') + RB(30, '2.9b V3<br>') +
            RB(31, '1.54b V2&ensp;') + RB(32, '2.13b V3<br>') +
            RB(33, '2.9 V2&ensp;') + RB(34, '4.2b V2<br>') +
            RB(35, '2.66b&ensp;') + RB(36, '5.83 V2<br>') +
            RB(37, '4.01 f&ensp;') + RB(38, '2.7b V2<br>') +
            RB(39, '2.13 V3&ensp;') + RB(40, '2.13 B V4<br>') +
            RB(41, '3.52&ensp;') + RB(42, '2.7 V2<br>') +
            RB(43, '2.13 V4&ensp;') + RB(44, '4.2 V2<br>') +
            RB(45, '13.3k&ensp;') + RB(46, '4.26<br>') +
            RB(47, '2.9bV4&ensp;') + RB(48, '13.3b<br>'));
    }
    function rbClick(index) {
        getElm('nud_w').value = +epdArr[index][0];
        getElm('nud_h').value = +epdArr[index][1];
        epdInd = index;
    }
</script>
<script type="text/javascript">

    var source;
    var dX, dY, dW, dH, sW, sH;
    function getVal(p, i) {
        if ((p.data[i] == 0x00) && (p.data[i + 1] == 0x00)) return 0;
        if ((p.data[i] == 0xFF) && (p.data[i + 1] == 0xFF)) return 1;
        if ((p.data[i] == 0x7F) && (p.data[i + 1] == 0x7F)) return 2;
        return 3;
    }
    function getVal_7color(p, i) {
        if ((p.data[i] == 0x00) && (p.data[i + 1] == 0x00) && (p.data[i + 2] == 0x00)) return 0;
        if ((p.data[i] == 0xFF) && (p.data[i + 1] == 0xFF) && (p.data[i + 2] == 0xFF)) return 1;
        if ((p.data[i] == 0x00) && (p.data[i + 1] == 0xFF) && (p.data[i + 2] == 0x00)) return 2;
        if ((p.data[i] == 0x00) && (p.data[i + 1] == 0x00) && (p.data[i + 2] == 0xFF)) return 3;
        if ((p.data[i] == 0xFF) && (p.data[i + 1] == 0x00) && (p.data[i + 2] == 0x00)) return 4;
        if ((p.data[i] == 0xFF) && (p.data[i + 1] == 0xFF) && (p.data[i + 2] == 0x00)) return 5;
        if ((p.data[i] == 0xFF) && (p.data[i + 1] == 0x80) && (p.data[i + 2] == 0x00)) return 6;
        return 7;
    }
    function setVal(p, i, c) {
        p.data[i] = curPal[c][0];
        p.data[i + 1] = curPal[c][1];
        p.data[i + 2] = curPal[c][2];
        p.data[i + 3] = 255;
    }
    function addVal(c, r, g, b, k) {
        return [c[0] + (r * k) / 32, c[1] + (g * k) / 32, c[2] + (b * k) / 32];
    }
    function getErr(r, g, b, stdCol) {
        r -= stdCol[0];
        g -= stdCol[1];
        b -= stdCol[2];
        return r * r + g * g + b * b;
    }
    function getNear(r, g, b) {
        var ind = 0;
        var err = getErr(r, g, b, curPal[0]);
        for (var i = 1; i < curPal.length; i++) {
            var cur = getErr(r, g, b, curPal[i]);
            if (cur < err) { err = cur; ind = i; }
        }
        return ind;
    }
</script>
<script type="text/javascript">
    function procImg(isLvl, isRed) {
        if (document.getElementsByClassName('sourceImage').length == 0) {
            alert('First select image');
            return;
        }
        var palInd = epdArr[epdInd][2];
        if (isRed && ((palInd & 1) == 0)) {
            alert('This white-black display');
            return;
        }
        if (!isRed) palInd = palInd & 0xFE;
        curPal = palArr[palInd];
        getElm('dstBox').innerHTML =
            '<span class="title">Processed image</span><br><canvas id="canvas"></canvas>';
        var canvas = getElm('canvas');
        sW = srcImg.width;
        sH = srcImg.height;
        source = getElm('source');
        source.width = sW;
        source.height = sH;
        source.getContext('2d').drawImage(srcImg, 0, 0, sW, sH);
        dX = parseInt(getElm('nud_x').value);
        dY = parseInt(getElm('nud_y').value);
        dW = parseInt(getElm('nud_w').value);
        dH = parseInt(getElm('nud_h').value);
        if ((dW < 3) || (dH < 3)) {
            alert('Image is too small');
            return;
        }
        canvas.width = dW;
        canvas.height = dH;
        var index = 0;
        var pSrc = source.getContext('2d').getImageData(0, 0, sW, sH);
        var pDst = canvas.getContext('2d').getImageData(0, 0, dW, dH);
        if (isLvl) {
            for (var j = 0; j < dH; j++) {
                var y = dY + j;
                if ((y < 0) || (y >= sH)) {
                    for (var i = 0; i < dW; i++, index += 4) setVal(pDst, index, (i + j) % 2 == 0 ? 1 : 0);
                    continue;
                }
                for (var i = 0; i < dW; i++) {
                    var x = dX + i;
                    if ((x < 0) || (x >= sW)) {
                        setVal(pDst, index, (i + j) % 2 == 0 ? 1 : 0);
                        index += 4;
                        continue;
                    }
                    var pos = (y * sW + x) * 4;
                    setVal(pDst, index, getNear(pSrc.data[pos], pSrc.data[pos + 1], pSrc.data[pos + 2]));
                    index += 4;
                }
            }
        } else {
            var aInd = 0;
            var bInd = 1;
            var errArr = new Array(2);
            errArr[0] = new Array(dW);
            errArr[1] = new Array(dW);
            for (var i = 0; i < dW; i++)
                errArr[bInd][i] = [0, 0, 0];
            for (var j = 0; j < dH; j++) {
                var y = dY + j;
                if ((y < 0) || (y >= sH)) {
                    for (var i = 0; i < dW; i++, index += 4)setVal(pDst, index, (i + j) % 2 == 0 ? 1 : 0);
                    continue;
                }
                aInd = ((bInd = aInd) + 1) & 1;
                for (var i = 0; i < dW; i++)errArr[bInd][i] = [0, 0, 0];
                for (var i = 0; i < dW; i++) {
                    var x = dX + i;
                    if ((x < 0) || (x >= sW)) {
                        setVal(pDst, index, (i + j) % 2 == 0 ? 1 : 0);
                        index += 4;
                        continue;
                    }
                    var pos = (y * sW + x) * 4;
                    var old = errArr[aInd][i];
                    var r = pSrc.data[pos] + old[0];
                    var g = pSrc.data[pos + 1] + old[1];
                    var b = pSrc.data[pos + 2] + old[2];
                    var colVal = curPal[getNear(r, g, b)];
                    pDst.data[index++] = colVal[0];
                    pDst.data[index++] = colVal[1];
                    pDst.data[index++] = colVal[2];
                    pDst.data[index++] = 255;
                    r = (r - colVal[0]);
                    g = (g - colVal[1]);
                    b = (b - colVal[2]);
                    if (i == 0) {
                        errArr[bInd][i] = addVal(errArr[bInd][i], r, g, b, 7.0);
                        errArr[bInd][i + 1] = addVal(errArr[bInd][i + 1], r, g, b, 2.0);
                        errArr[aInd][i + 1] = addVal(errArr[aInd][i + 1], r, g, b, 7.0);
                    } else if (i == dW - 1) {
                        errArr[bInd][i - 1] = addVal(errArr[bInd][i - 1], r, g, b, 7.0);
                        errArr[bInd][i] = addVal(errArr[bInd][i], r, g, b, 9.0);
                    } else {
                        errArr[bInd][i - 1] = addVal(errArr[bInd][i - 1], r, g, b, 3.0);
                        errArr[bInd][i] = addVal(errArr[bInd][i], r, g, b, 5.0);
                        errArr[bInd][i + 1] = addVal(errArr[bInd][i + 1], r, g, b, 1.0);
                        errArr[aInd][i + 1] = addVal(errArr[aInd][i + 1], r, g, b, 7.0);
                    }
                }
            }
        }
        canvas.getContext('2d').putImageData(pDst, 0, 0);
    }
</script>

<script type="text/javascript">
    var pxInd, stInd;
    var dispW, dispH;
    var xhReq, dispX;
    var rqPrf, rqMsg;
    function byteToStr(v) { return String.fromCharCode((v & 0xF) + 97, ((v >> 4) & 0xF) + 97); }
    function wordToStr(v) { return byteToStr(v & 0xFF) + byteToStr((v >> 8) & 0xFF); }
    function u_send(cmd, next) {
        /* 配置POST请求,异步模式(第三个参数) */
        xhReq.open('POST', rqPrf + cmd, true);
        xhReq.send('');
        if (next)
            stInd++;
        return 0;
    }
    function u_next() {
        lnInd = 0;
        pxInd = 0;
        u_send('NEXT_', true);
    }
    function u_done() {
        setInn('logTag', 'Complete!');
        return u_send('SHOW_', true);
    }
    function u_show(a, k1, k2) { var x = '' + (k1 + k2 * pxInd / a.length); if (x.length > 5) x = x.substring(0, 5); setInn('logTag', 'Progress: ' + x + '%'); return u_send(rqMsg + wordToStr(rqMsg.length) + 'LOAD_', pxInd >= a.length); }
    function u_data(a, c, k1, k2) {
        rqMsg = '';
        if (c == -1) {
            while ((pxInd < a.length) && (rqMsg.length < 1000)) {
                var v = 0;
                for (var i = 0; i < 16; i += 2)if (pxInd < a.length) v |= (a[pxInd++] << i);
                rqMsg += wordToStr(v);
            }
        }
        else if (c == -2) {
            while ((pxInd < a.length) && (rqMsg.length < 1000)) {
                var v = 0;
                for (var i = 0; i < 16; i += 4)if (pxInd < a.length) v |= (a[pxInd++] << i);
                rqMsg += wordToStr(v);
            }
        }
        else {
            while ((pxInd < a.length) && (rqMsg.length < 1000)) {
                var v = 0;
                for (var i = 0; i < 8; i++) if ((pxInd < a.length) && (a[pxInd++] != c)) v |= (128 >> i);
                rqMsg += byteToStr(v);
            }
        }
        return u_show(a, k1, k2);
    }
    function u_line(a, c, k1, k2) {
        var x;
        rqMsg = '';
        while (rqMsg.length < 1000) {
            x = 0;
            while (x < 122) {
                var v = 0;
                for (var i = 0; (i < 8) && (x < 122); i++, x++) if (a[pxInd++] != c) v |= (128 >> i);
                rqMsg += byteToStr(v);
            }
        }
        return u_show(a, k1, k2);
    }
    function uploadImage() {
        var c = getElm('canvas');
        var w = dispW = c.width;
        var h = dispH = c.height;
        var p = c.getContext('2d').getImageData(0, 0, w, h);
        var a = new Array(w * h);
        var i = 0;
        for (var y = 0; y < h; y++)for (var x = 0; x < w; x++, i++) {
            if (epdInd == 25 || epdInd == 37)
                a[i] = getVal_7color(p, i << 2);
            else
                a[i] = getVal(p, i << 2);
        }
        dispX = 0;
        pxInd = 0;
        stInd = 0;
        xhReq = new XMLHttpRequest();
        rqPrf = 'http://' + getElm('ip_addr').value + '/';
        if ((epdInd == 3) || (epdInd == 39) || (epdInd == 43)) {
            xhReq.onload = xhReq.onerror = function () {
                if (stInd == 0) return u_line(a, 0, 0, 100);
                if (stInd == 1) return u_done();
            };
            if (epdInd > 25)
                return u_send('EPD' + String.fromCharCode(epdInd + -26 + 65) + '_', false);
            return u_send('EPD' + String.fromCharCode(epdInd + 97) + '_', false);
        }
        if ((epdInd == 40)) {
            xhReq.onload = xhReq.onerror = function () {
                if (stInd == 0) return u_line(a, 0, 0, 50);
                if (stInd == 1) return u_next();
                if (stInd == 2) return u_line(a, 3, 50, 50);
                if (stInd == 3) return u_done();
            };
            if (epdInd > 25)
                return u_send('EPD' + String.fromCharCode(epdInd + -26 + 65) + '_', false);
            return u_send('EPD' + String.fromCharCode(epdInd + 97) + '_', false);
        }
        if ((epdInd == 0) || (epdInd == 3) || (epdInd == 6) || (epdInd == 7) || (epdInd == 9) || (epdInd == 12) || (epdInd == 16) || (epdInd == 19) || (epdInd == 22) || (epdInd == 26) || (epdInd == 27) || (epdInd == 28)) {
            xhReq.onload = xhReq.onerror = function () {
                if (stInd == 0)
                    return u_data(a, 0, 0, 100);
                if (stInd == 1)
                    return u_done();
            };
            if (epdInd > 25)
                return u_send('EPD' + String.fromCharCode(epdInd + -26 + 65) + '_', false);
            return u_send('EPD' + String.fromCharCode(epdInd + 97) + '_', false);
        }
        if (epdInd > 15 && epdInd < 22) {
            xhReq.onload = xhReq.onerror = function () {
                if (stInd == 0)
                    return u_data(a, -1, 0, 100);
                if (stInd == 1)
                    return u_done();
            };
            return u_send('EPD' + String.fromCharCode(epdInd + 97) + '_', false);
        }
        if (epdInd == 25 || epdInd == 37) {
            xhReq.onload = xhReq.onerror = function () {
                if (stInd == 0)
                    return u_data(a, -2, 0, 100);
                if (stInd == 1)
                    return u_done();
            };
            if (epdInd > 25)
                return u_send('EPD' + String.fromCharCode(epdInd + -26 + 65) + '_', false);
            return u_send('EPD' + String.fromCharCode(epdInd + 97) + '_', false);
        }
        else {
            xhReq.onload = xhReq.onerror = function () {
                console.log('*************');
                console.log(stInd);
                console.log('*************');
                if (stInd == 0 && epdInd == 23)
                    return u_data(a, 0, 0, 100);
                if (stInd == 0)
                    return u_data(a, ((epdInd == 1) || (epdInd == 12)) ? -1 : 0, 0, 50);
                if (stInd == 1)
                    return u_next();
                if (stInd == 2)
                    return u_data(a, 3, 50, 50);
                if (stInd == 3)
                    return u_done();
            };
            if (epdInd > 25)
                return u_send('EPD' + String.fromCharCode(epdInd + -26 + 65) + '_', false);
            return u_send('EPD' + String.fromCharCode(epdInd + 97) + '_', false);
        }
    }
</script>

<table class="fixed" border="20">
    <col width="80%" />
    <tr>
        <td>
            <table border="2">
                <tr>
                    <td>
                        <h3>ESP32 File Server</h3>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="newfile">Upload a file</label>
                    </td>
                    <td colspan="2">
                        <input id="newfile" type="file" onchange="setpath()" style="width:100%;">
                    </td>
                </tr>
                <tr>
                    <td  style="width:30%;">
                        <label for="filepath">Set path on server</label>
                    </td>
                    <td  style="width:50%;">
                        <input id="filepath" type="text" style="width:100%;">
                    </td>
                    <td  style="width:20%;">
                        <button id="upload" type="button" onclick="upload()">Upload</button>
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>



<div class="header_back">
    <div class="header_face"></div>
</div>


<div class="content_back">
    <div class="content_face">
        <table style="width:100%; height:100%" border="0" cellspacing="0">
            <tr>
                <td class="menu_bar" rowspan="2">
                    <div id="BT"></div>
                    <table>
                        <tr>
                            <td class="comment" colspan="4">
                                <br>Device IP:
                            </td>
                        </tr>
                        <tr>
                            <td colspan="4">
                                <input id="ip_addr" style="width:100%;text-align:center" type="text"
                                    value="192.168.1.211">
                            </td>
                        </tr>
                        <tr>
                            <td class="comment" colspan="4">
                                <br>Bounds:
                            </td>
                        </tr>
                        <tr id="XY"></tr>
                        <tr id="WH"></tr>
                    </table>
                    <div id="RB"></div>
                </td>
                <td class="content_body">
                    <span class="title">Original image</span>
                    <br>
                    <canvas id="source" class="hidden_input"></canvas>
                    <div id="srcBox">
                        <div class="imgBox">
                            <div class="mesBox">Drop image here...</div>
                        </div>
                    </div>
                </td>
            </tr>
            <tr>
                <td id="dstBox" class="content_body"></td>
            </tr>
        </table>
    </div>
</div>


<div class="footer_back">
    <div class="footer_face" id="logTag"></div>
</div>


<script>
    function setpath() {
        var default_path = document.getElementById("newfile").files[0].name;
        document.getElementById("filepath").value = default_path;
    }
    function upload() {
        /* 执行6个验证条件(文件选择、路径设置、空格检查、路径结尾、文件大小) */
        const fileInput = document.getElementById("newfile").files;
        const filePath = document.getElementById("filepath").value.trim();
        const upload_path = "/upload/" + filePath;
        // alert(upload_path);

        /* Max size of an individual file. Make sure this value is same as that set in file_server.c */
        var MAX_FILE_SIZE = 200 * 1024;
        var MAX_FILE_SIZE_STR = "200KB";

        if (fileInput.length == 0) {
            alert("No file selected!");
        } else if (filePath.length == 0) {
            alert("File path on server is not set!");
        } else if (filePath.indexOf(' ') >= 0) {
            alert("File path on server cannot have spaces!");
        } else if (filePath[filePath.length - 1] == '/') {
            alert("File name not specified after path!");
        } else if (fileInput[0].size > 200 * 1024) {
            alert("File size must be less than 200KB!");
        } else {
            /* 禁用表单元素 */
            document.getElementById("newfile").disabled = true;
            document.getElementById("filepath").disabled = true;
            document.getElementById("upload").disabled = true;  

            /* 通过传统 XMLHttpRequest 实现文件上传功能 */
            var file = fileInput[0];
            var xhttp = new XMLHttpRequest();
            /* 设置请求状态变更时的回调函数 */
            xhttp.onreadystatechange = function () {

                /* 检查请求是否完成 */
                if (xhttp.readyState == 4) {
                    /* 检查HTTP状态码是否为200(成功) */
                    if (xhttp.status == 200) {
                        /* 打开当前文档(准备写入) */
                        document.open();
                        /* 将服务器响应内容写入文档 */
                        document.write(xhttp.responseText);
                        /* 关闭文档写入模式 */
                        document.close();

                    /* 处理服务器主动关闭连接的情况 */
                    } else if (xhttp.status == 0) {
                        alert("Server closed the connection abruptly!");
                        location.reload()
                    } else {
                        alert(xhttp.status + " Error!\n" + xhttp.responseText);
                        location.reload()
                    }
                }
            };
            /* 配置POST请求,异步模式(第三个参数) */
            xhttp.open("POST", upload_path, true);
            xhttp.send(file);
        }
    }
</script>

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐