Продолжаем работу с нашим сервером HTTP и на данном уроке мы попробуем расположить контент для ответа клиенту в пространстве файловой системы SPIFFS, с которой мы познакомились, а вернее, продолжили знакомство на прошлом уроке. Причём мы уже практически весь нужный контент (страничку и иконку) уже разместили в данной файловой системе. Схема наша также осталась прежней — отладочная плата с контроллером ESP32, подключенная к USB-порту компьютера
Проект мы будем использовать из урока 28 с именем WIFI_STA_HTTP_SERVER_IDF и присвоим ему новое имя WIFI_STA_HTTP_SERVER_SPIFFS.
В каталог с проектом скопируем файл partitions.csv из проекта прошлого урока с именем SPIFFS.
Откроем проект в Espressif IDE и в конфигураторе выберем способ использования таблицы разделов — custom
В файле main.h подключим заголовочные файлы для работы с файловой системой
В функции app_main файла main.c добавим код для инициализации файловой системы практически такой же как и в прошлом занятии, только без просмотра и записи файлов
В файле http.c удалим объявление и инициализацию массивов index_html и favicon_ico, так как данные файлы у нас уже есть в нашей файловой системе.
Объявим макрос для сравнения расширения файла с некоторыми известными типами, а также добавим функцию, которая будет определять тип файла для дальнейшего формирования полей заголовка ответа клиенту, а заодно его и сформирует сразу
Ниже добавим функцию, которая будет определять путь к файлу
Вычислим длину строки пути
Аналогично вычислим длину строки идентификатора ресурса
Узнаем, есть ли параметры, если есть то сохраним позицию их начала
В файле http.h подключим файл для работы с параметрами
Вернёмся в http.c в функцию get_path_from_uri и, если параметры есть, то изменим длину пути, если позиция параметров меньше длины пути
Аналогично поступим с хештегами
Если путь получился слишком длинным (больше чем максимальный во входящем аргументе функции), то выходим из функции
А если всё нормально, то соберём наш путь в единую строку и возвратим указатель
Функцию all_get_handler переименуем
static esp_err_t download_get_handler(httpd_req_t *req)
Так как в данной функции будет очень много изменений, то тело очистим полностью.
В файле http.h подключим заголовочный файл для работы с виртуальной файловой системой, объявим макрос, который определит максимальный размер пути к файлу, также объявим макрос максимального размера считываемого фрагмента файла и структуру для данных файла сервера
Вернёмся в http.c и в теле функции download_get_handler объявим символьный массив для пути к файлу, указатель на дескриптор файла и также переменную типа структуры состояния файла
Определим путь к файлу
Если NULL, то выведем в терминале соответствующее сообщение и вернём клиенту страницу ошибки
Если слэш, то будем считать, что клиенту надо передать файл index.html
Узнаем состояние файла
Попытаемся открыть файл на чтение
Если файл не существует, выведем соответствующее сообщение в терминал и отправим клиенту страницу с ошибкой
Если всё нормально, то выведем в терминал информацию о файле: его имя и размер
При помощи добавленной нами выше функции сформируем поле типа файла заголовка HTTP
Найдём позицию начала контента
Считаем контент при помощи цикла, в котором будем определять размер и разбивать контент на части, передавая клиенту каждую из них
Закроем файл, выведем сообщение в терминал о том, что файл передан, передадим пустой пакет, означающий окончание документа и вернём ноль.
Удалим функцию favicon_get_handler, так как у нас теперь есть универсальная функция, передающая любые файлы, а также переменные all и favicon_uri.
В функции start_webserver объявим указатель на переменную типа структуры данных файла сервера
Если такой указатель уже существует, то выведем соответствующее сообщение в терминал и уйдём из функции с соответствующей ошибкой
А если всё нормально, то выделим память под данную структуру
Если выделить память не удалось, также уйдём из функции с соответствующей ошибкой
А если удалось, то скопируем путь к файлу в соответствующее поле структуры
Соответствующему полю переменной типа структуры конфигурации сервера присвоим адрес функции проверки соответствия шаблону URI
После следующей строки
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
удалим весь код функции.
Попытаемся запустить наш сервер и в случае неудачи уйдём из функции, выведя соответствующее сообщение в терминал
Зарегистрируем URI и выйдем из функции с нулём (ESP_OK)
Соберём код, прошьём контроллер и узнаем IP-адрес нашего HTTP-сервера в терминале
Отфильтруемся по данному адресу в WireShark и введём его в браузере
Отлично! Наш клиент всё получил. И страничку, и иконку, что подтверждается иконкой в заголовке закладки.
Также мы весь обмен видим и в WireShark
В терминале мы также видим всю передачу вместе с именами и размерами файлов
Всем спасибо за внимание!
Оригинал статьи находится здесь.
<<Предыдущий урок | Следующий урок>>
Утилита для работы с файловой системой SPIFFS: mkspiffs
Недорогие отладочные платы ESP32 можно купить здесь
Недорогие отладочные платы ESP32/ESP32-C3/ESP32-S3 можно купить здесь
Логический анализатор 16 каналов можно приобрести здесь
Многофункциональный переходник CJMCU FT232H USB к JTAG UART FIFO SPI I2C можно купить здесь
Видео в Rutube
Видео в Дзен
Видео в Youtube