• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Решено Как отправить от HTTP сервера (Web server на ESP8266) html-ответ в браузер компьютера файлом?

Paul_B

Member
Есть HTTP сервер на ESP8266, который по запросам с компьютера отправляет html-ответы в виде интернет-страничек. Размер их может достигать до 10кб. Отправку осуществляю командой
Код:
server.send(200,"text/html", str)
где сформированная html-страничка находится в строковой переменной str.
Иногда она формируется нулевой длины, что связываю с возникновением глюков из-за большого размера (до 10 тыс знаков) и нехватки памяти.
Можно ли как-то формировать файл в SPIFFS, записывая в него кусочками (по 100-200 знаков) всю страницу, а потом отправить сразу весь записанный файл, минуя его предварительное чтение и преобразование через строковую переменную?
 
Последнее редактирование:

Юрий Ботов

Moderator
Команда форума
помнится мне там кроме .send( есть еще и .send_P( для непосредственной адресации к флэшу. Не к файлу, а просто к строке во флэше.
 

Paul_B

Member
помнится мне там кроме .send( есть еще и .send_P( для непосредственной адресации к флэшу. Не к файлу, а просто к строке во флэше.
Говорят, на сайте есть пример от Гуру, но я не нашел. Т.е. проблема понятна - как отправить большую html страницу минуя ее преобразование в строковую переменную. ну, или как ее отправить частями. но во втором случае не обойтись без java
 

Paul_B

Member
Вот как получилось:
Код:
File file = SPIFFS.open("/index.html", "w");
 file.print(.....);
........
file.print(.....);
file.close();
 
file = SPIFFS.open("/index.html", "r");
size_t sent = server.streamFile(file, "text/html");
file.close();
Т.е. я формирую html- файлы в теле скетча, поскольку они зависят от многих параметров, т.к. я реализую сеть из ESP8266 произвольного числа, которые сами объединяются так, чтобы все модули были в одной сети и возможно было с любого управлять любым, включая изменять настройки.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
@Paul_B и сколько у вас так Флэш проживет? Не лучше отправлять из флеш-памяти только неизменяемые части, а подставлять параметры "на лету"?
 

Paul_B

Member
@Paul_B и сколько у вас так Флэш проживет? Не лучше отправлять из флеш-памяти только неизменяемые части, а подставлять параметры "на лету"?
Кстати, SPIFFS - энергонезависим? Т.е., при отключении питания там файлы сохраняются?
Пусть возможен 100 000 режимов записи. Если входить через HTTP даже 10 раз в день, то это хватит на 30 лет. Я столько не проживу. Это раз.
А если подставлять "на лету", это значит я должен опять считать в строковую переменную, это не пойдет. Или есть способ отправить HTML станицу двумя кусками? Способ, что сначала написать код страницы, а потом подсасывать в нее параметры не подойдет, потому что связан с изучением всяких java. Создать целиком страницу и целиком ее передать в браузер я еще освоил, освоил передачу параметров от браузера в ESP, а вот как разбирать параметры от ESP внутри HTML для меня темный лес.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
@Paul_B конечно энергонезависимый, но довольно медленный на запись. Вы уверены что это вас устроит? Страницу можно отдавать хоть 10-ю частями. А лучше потратить немного времени и изучить AJAX - будет потом проще и удобнее.
 

Сергей_Ф

Moderator
Команда форума
@Paul_B , честно говоря, не знаю даже что сказать. Просто берете и посылаете двумя частями. Или тремя. Или 10-ю. Да хоть по одному символу посылайте. Html-заканчива там, где он закончится. Извините за каламбур.

Посмотрите простейший проект https://esp8266.ru/forum/threads/prostye-wifi-chasy.1209/
 

Paul_B

Member
Просто берете и посылаете двумя частями. Или тремя. Или 10-ю. Да хоть по одному символу посылайте.
А мне всегда казалось, что в браузере функция приема аналогична записи в файл с опцией "w", т.е. каждая новая посылка сбрасывает указатель на ноль, т.е. затирает переданные до нее в браузере. А вы утверждаете, что посылать можно как при опции записи "a", т.е. с продолжением. Надо попробовать.
 

Paul_B

Member
Говорят, на сайте есть пример от Гуру, но я не нашел. Т.е. проблема понятна - как отправить большую html страницу минуя ее преобразование в строковую переменную. ну, или как ее отправить частями. но во втором случае не обойтись без java

Код:
size_t server_sendfile(const String& fn)
{
File f=SPIFFS.open(fn, "r");
if(f)
    {
      char buf[1024];
      size_t sent = 0;
      int siz = f.size();
      Serial.println("\nSend file "+fn+" size="+String(siz));
      while(siz > 0) {
        size_t len = std::min((int)(sizeof(buf) - 1), siz);
        f.read((uint8_t *)buf, len);
      //  Serial.println(buf);
        server.client().write((const char*)buf, len);
        siz -= len;
        sent+=len;
      }
     f.close();  
     Serial.println(" sended "+String(sent));
     return(sent);  
    }
else Serial.println("Bad open file "+fn);  
return(0);  
}
 

Алексей.

Active member
Paul_B,
Всю статику прям в коде (в прошивке) держу, в виде массива байтов, к счастью есп поддерживает режим progmem и данные мапятся прямо на флеш. Скрипты, стили страницы - пережаты gzip-ом, картинки нет смысла жать, поэтому так лежат.
В прошивку положил потому что загружается прошивка в модуль быстро, а загрузка файлов на spiffs кажется вечностью.
Отгружаю контент броузеру или одним куском, если данных не много
Код:
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(code, dataType);
server.sendContent_P(content, size);
или частями (бутстрап и джи-квери хоть и пережал, но всё равно тяжелые)
Код:
#define CONTENT_BLOCK_MAX 2048

server.sendHeader("Content-Encoding", "gzip");
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, dataType, "");
size_t offset;
for (offset = 0; offset < size; ) {
  size_t bytes = (size - offset) >= CONTENT_BLOCK_MAX ? CONTENT_BLOCK_MAX : size - offset;
  server.sendContent_P(content + offset, bytes);
  offset += bytes;
}
 
Последнее редактирование:

Paul_B

Member
Вот окончательно сделал замену вечно лагающему .streamFile
Код:
size_t server_sendfile(String fn)
{
if(!fn.startsWith("/")) fn="/"+fn;
File f=SPIFFS.open(fn, "r");
if(f)
    {
      char buf[2048];
      size_t sent = 0;
      int siz = f.size();
      String S="HTTP/1.1 200\r\nContent-Type: "+ getContentType(fn) +"\r\nContent-Length: "+ String(siz)+"\r\nConnection: close\r\n\r\n";
      server.client().write(S.c_str(), S.length());
      Serial.println("\nSend file "+fn+" size="+String(siz));
      while(siz > 0) {
        size_t len = std::min((int)(sizeof(buf) - 1), siz);
        f.read((uint8_t *)buf, len);
        server.client().write((const char*)buf, len);
        siz -= len;
        sent+=len;
      }
     f.close();  
     Serial.println(" sended "+String(sent));
     return(sent);  
    }
else {
  server.send(404, "text/plain", "FileNotFound");
  Serial.println("Bad open file "+fn);
}
return(0);  
}
 

Legion12

New member
Paul_B,
Всю статику прям в коде (в прошивке) держу, в виде массива байтов, к счастью есп поддерживает режим progmem и данные мапятся прямо на флеш. Скрипты, стили страницы - пережаты gzip-ом, картинки нет смысла жать, поэтому так лежат.
В прошивку положил потому что загружается прошивка в модуль быстро, а загрузка файлов на spiffs кажется вечностью.
Отгружаю контент броузеру или одним куском, если данных не много
Код:
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(code, dataType);
server.sendContent_P(content, size);
Черт возьми, всего Вам доброго и хорошего ))))))))))))) Вы просто спасли меня!
 

Paul_B

Member
void ESP8266WebServer::sendContent_P ( PGM_P content, size_t size )

Извините, а что такое PGM_P и что выступает в роли content?
 

Paul_B

Member
void ESP8266WebServer::sendContent_P ( PGM_P content, size_t size )

Извините, а что такое PGM_P и что выступает в роли content?
 

Paul_B

Member
В Spiffs есть куча файликов. Можно как-то из скетча запустить exe-архиватор (тоже лежит в Spiffs), а потом созданный архив одним файлом скачать на диск (это я умею). Вопрос - как средствами Arduino ide запустить exe файл в Spiffs?
 

Алексей.

Active member
Можно как-то из скетча запустить exe-архиватор
Из скетча?? Это код выполняется на модуле, что он запустить должен?
Вопрос - как средствами Arduino ide запустить exe файл
Хуками, определяйте в platform.local.txt что выполнять, например recipe.hooks.sketch.prebuild.0.pattern и каждый раз при сборке (когда нажимаете в ардуино-иде кнопку "Проверить") будет выполняться ваш код (то что определите в хуке). Подробно тут.

П.С.
Для пережатия файлов gzip-ом, не требуются дополнительное ПО. Достаточно средств в ОС, на виндовс powershell-ом (скриптом) замечательно архивируется.
 
Сверху Снизу