Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

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

Тема в разделе "ESP8266 Arduino IDE", создана пользователем Paul_B, 2 фев 2018.

  1. Paul_B

    Paul_B Новичок

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

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.050
    Симпатии:
    175
    помнится мне там кроме .send( есть еще и .send_P( для непосредственной адресации к флэшу. Не к файлу, а просто к строке во флэше.
     
  3. Paul_B

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    Говорят, на сайте есть пример от Гуру, но я не нашел. Т.е. проблема понятна - как отправить большую html страницу минуя ее преобразование в строковую переменную. ну, или как ее отправить частями. но во втором случае не обойтись без java
     
  4. Paul_B

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    Вот как получилось:
    Код (Text):
    1.  
    2. File file = SPIFFS.open("/index.html", "w");
    3.  file.print(.....);
    4. ........
    5. file.print(.....);
    6. file.close();
    7.  
    8. file = SPIFFS.open("/index.html", "r");
    9. size_t sent = server.streamFile(file, "text/html");
    10. file.close();
    Т.е. я формирую html- файлы в теле скетча, поскольку они зависят от многих параметров, т.к. я реализую сеть из ESP8266 произвольного числа, которые сами объединяются так, чтобы все модули были в одной сети и возможно было с любого управлять любым, включая изменять настройки.
     
    Последнее редактирование: 3 фев 2018
  5. Сергей_Ф

    Сергей_Ф Moderator Команда форума

    Сообщения:
    2.148
    Симпатии:
    226
    @Paul_B и сколько у вас так Флэш проживет? Не лучше отправлять из флеш-памяти только неизменяемые части, а подставлять параметры "на лету"?
     
  6. Paul_B

    Paul_B Новичок

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

    Сергей_Ф Moderator Команда форума

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

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    Можно посоветовать как передать строку <html>......</html> в браузер хотя бы 2-мя частями.
     
  9. Сергей_Ф

    Сергей_Ф Moderator Команда форума

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

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

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    А мне всегда казалось, что в браузере функция приема аналогична записи в файл с опцией "w", т.е. каждая новая посылка сбрасывает указатель на ноль, т.е. затирает переданные до нее в браузере. А вы утверждаете, что посылать можно как при опции записи "a", т.е. с продолжением. Надо попробовать.
     
  11. Paul_B

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3

    Код (Text):
    1. size_t server_sendfile(const String& fn)
    2. {
    3. File f=SPIFFS.open(fn, "r");
    4. if(f)
    5.     {
    6.       char buf[1024];
    7.       size_t sent = 0;
    8.       int siz = f.size();
    9.       Serial.println("\nSend file "+fn+" size="+String(siz));
    10.       while(siz > 0) {
    11.         size_t len = std::min((int)(sizeof(buf) - 1), siz);
    12.         f.read((uint8_t *)buf, len);
    13.       //  Serial.println(buf);
    14.         server.client().write((const char*)buf, len);
    15.         siz -= len;
    16.         sent+=len;
    17.       }
    18.      f.close();  
    19.      Serial.println(" sended "+String(sent));
    20.      return(sent);  
    21.     }
    22. else Serial.println("Bad open file "+fn);  
    23. return(0);  
    24. }
     
  12. Алексей.

    Алексей. Авторитетный участник сообщества

    Сообщения:
    534
    Симпатии:
    62
    Paul_B,
    Всю статику прям в коде (в прошивке) держу, в виде массива байтов, к счастью есп поддерживает режим progmem и данные мапятся прямо на флеш. Скрипты, стили страницы - пережаты gzip-ом, картинки нет смысла жать, поэтому так лежат.
    В прошивку положил потому что загружается прошивка в модуль быстро, а загрузка файлов на spiffs кажется вечностью.
    Отгружаю контент броузеру или одним куском, если данных не много
    Код (C):
    1.  
    2. server.setContentLength(CONTENT_LENGTH_UNKNOWN);
    3. server.send(code, dataType);
    4. server.sendContent_P(content, size);
    5.  
    или частями (бутстрап и джи-квери хоть и пережал, но всё равно тяжелые)
    Код (C):
    1.  
    2. #define CONTENT_BLOCK_MAX 2048
    3.  
    4. server.sendHeader("Content-Encoding", "gzip");
    5. server.setContentLength(CONTENT_LENGTH_UNKNOWN);
    6. server.send(200, dataType, "");
    7. size_t offset;
    8. for (offset = 0; offset < size; ) {
    9.   size_t bytes = (size - offset) >= CONTENT_BLOCK_MAX ? CONTENT_BLOCK_MAX : size - offset;
    10.   server.sendContent_P(content + offset, bytes);
    11.   offset += bytes;
    12. }
    13.  
     
    Последнее редактирование: 11 сен 2018
    Legion12 нравится это.
  13. Paul_B

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    Вот окончательно сделал замену вечно лагающему .streamFile
    Код (Text):
    1.  
    2. size_t server_sendfile(String fn)
    3. {
    4. if(!fn.startsWith("/")) fn="/"+fn;
    5. File f=SPIFFS.open(fn, "r");
    6. if(f)
    7.     {
    8.       char buf[2048];
    9.       size_t sent = 0;
    10.       int siz = f.size();
    11.       String S="HTTP/1.1 200\r\nContent-Type: "+ getContentType(fn) +"\r\nContent-Length: "+ String(siz)+"\r\nConnection: close\r\n\r\n";
    12.       server.client().write(S.c_str(), S.length());
    13.       Serial.println("\nSend file "+fn+" size="+String(siz));
    14.       while(siz > 0) {
    15.         size_t len = std::min((int)(sizeof(buf) - 1), siz);
    16.         f.read((uint8_t *)buf, len);
    17.         server.client().write((const char*)buf, len);
    18.         siz -= len;
    19.         sent+=len;
    20.       }
    21.      f.close();  
    22.      Serial.println(" sended "+String(sent));
    23.      return(sent);  
    24.     }
    25. else {
    26.   server.send(404, "text/plain", "FileNotFound");
    27.   Serial.println("Bad open file "+fn);
    28. }
    29. return(0);  
    30. }
     
  14. Legion12

    Legion12 Новичок

    Сообщения:
    4
    Симпатии:
    0
    Черт возьми, всего Вам доброго и хорошего ))))))))))))) Вы просто спасли меня!
     
  15. Paul_B

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    void ESP8266WebServer::sendContent_P ( PGM_P content, size_t size )

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

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    void ESP8266WebServer::sendContent_P ( PGM_P content, size_t size )

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

    Paul_B Новичок

    Сообщения:
    129
    Симпатии:
    3
    Разобрался
     
  18. Paul_B

    Paul_B Новичок

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

    Алексей. Авторитетный участник сообщества

    Сообщения:
    534
    Симпатии:
    62
    Из скетча?? Это код выполняется на модуле, что он запустить должен?
    Хуками, определяйте в platform.local.txt что выполнять, например recipe.hooks.sketch.prebuild.0.pattern и каждый раз при сборке (когда нажимаете в ардуино-иде кнопку "Проверить") будет выполняться ваш код (то что определите в хуке). Подробно тут.

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

Поделиться этой страницей