• Skip to main content
  • Skip to primary sidebar

RNTLab.com

The Ultimate Shortcut to Learn Electronics and Programming with Open Source Hardware and Software

  • Courses
  • Forum
    • Forum
    • Ask Question
  • Shop
  • Account
  • Blog
  • Login

Asyncwebserver using server unc placerholders with processor template

Q&A Forum › Asyncwebserver using server unc placerholders with processor template
0 Vote Up Vote Down
William Lucid asked 4 years ago

Good Afternoon,

Working on the RainGauge Log page; trying to make file name a variable in the server unc path.  Issue I am running into is a hard coded path works:

“<div><object data=http://xx.xxx.xxx.xxx:yyyy/LOG06242021.TXT width=”100%” height=”700″></object></div>”

One with a placeholder does not load the text file:

“<div><object data=http://xx.xxx.xxx.xxx:yyyy/%UNCFB% width=”100%” height=”700″></object></div>”

William

Question Tags: Asyncwebserver, ESP32, Placeholder
20 Answers
0 Vote Up Vote Down
William Lucid answered 4 years ago

Found my mistake; placed placeholders in the wrong String processor (Code has six String processors.)

Server unc path with placeholders:
“<div><object data=http://%LINK%/%UNCFN% width=”100%” height=”700″></object></div>”

Have been working on adding a hyperlink to displayed log file.  Only have it working in a round about way; first select “File Browser” to list all Log files, then selc option “Show Log File” will display Log file again.  This time the displayed displayed Log file will have a  hyperlink to “SdBrowse.”

Variable for filename is extracted when the “SdBrowse” can not find the filename; using the “notFound” function the filename gets “retrieved” making the filename avaiable for the “Show Log File” option.

ESP32 Asyncwebserver project website

Looking for way to go directly to “Show Log File;”  from notFound function.

“request->send(SPIFFS, fn, String(), false);” is used to display Log file.

ESP32 RainGauge project code

Features of the ESP32 RainGauge Project

Show Log File:


serverAsync.on(“/Show”, HTTP_GET, [](AsyncWebServerRequest * request)
{

PATH = “/Show”;
accessLog();
if (! flag == 1)
{

request->send_P(200, PSTR(“text/html”), HTML6, processor6);

}
end();
});

William

 

0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi William.
I’m glad you found the issue.
Is there anything else that I can help you with?
Regards,
Sara

0 Vote Up Vote Down
William Lucid answered 4 years ago

Good Morning Sara,

Looking for way to go directly to “Show Log File;”  from notFound function.

notFound function:

String notFound(AsyncWebServerRequest *request)
{

digitalWrite(online, HIGH);   //turn-on online LED indicator

if (! request->url().endsWith(F(“.TXT”)))
{
request->send(404);
}
else
{
if (request->url().endsWith(F(“.TXT”)))
{
//.endsWith(F(“.txt”)))

// here comes some mambo-jambo to extract the filename from request->url()
int fnsstart = request->url().lastIndexOf(‘/’);

fn = request->url().substring(fnsstart);

uncfn = fn.substring(1);

PATH = fn;

//accessLog();

File webFile = SPIFFS.open(fn);

Serial.print(“File size: “);

Serial.println(webFile.size());

if (!webFile)
{

Serial.println(“File:  ” + fn + ” failed to open”);
Serial.println(“\n”);

}
else if (webFile.size() == 0)
{

webFile.close();

}
else
{

//request->send(SPIFFS, fn, String(), true);  //Download file
request->send(SPIFFS, fn, String(), false);  //Display file

//This what I am trying to do… without a GET request.
//request->send_P(200, PSTR(“text/html”), HTML6, processor6);

//When I try this I see “Collected Observations” and “SdBrowse” from index6.h (HTML) wirh no text.

 

webFile.close();

}

fn = “”;

end();

}

}

digitalWrite(online, LOW);   //turn-off online LED indicator

return(uncfn);

}

William
0 Vote Up Vote Down
William Lucid answered 4 years ago

Good Morning,

Clarification:  notFound fuction is not able to do what I am trying to accomplish.

//From inside of the notFound function:
//This what I am trying to do… without a GET request.
//request->send_P(200, PSTR(“text/html”), HTML6, processor6);

This what I need to send in the notFound function:
//index6.h

const char HTML6[] PROGMEM = R”====(
<!DOCTYPE HTML>
<html>

<head>
<title>Observations</title>
</head>

<body>
<h2>Collected Observations
<br>
<br> <div><object data=http://%LINK%/%UNCFN% width=”100%” height=”700″></object></div>
<br>
<br>
<a href=http://%LINK%/SdBrowse >SdBrowse</a></h2><br>
</body>

</html>
)====”;

William

0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi William.
 
Thanks for the clarification. Now, I think I understood what you are trying to do.
You want to send a file when the notFound function is triggered.
 
Here’s something that you need to keep in mind: with HTTP requests, you can only send a response if you are requested something.
If you want to send information from the server to the client without being requested, you can use server-sent events or WebSocket protocol. However, at the moment, I don’t have any tutorials about sending files via these protocols. But, it should be possible to implement.
 
Have you taken a look at the notFound() function implementation in the AsyncWebServer documentation: https://github.com/me-no-dev/ESPAsyncWebServer
In what scenario should that function run?
What happens when you run the command you’ve shown before?

//request->send_P(200, PSTR(“text/html”), HTML6, processor6);

 
Regards,
Sara
 
 

0 Vote Up Vote Down
William Lucid answered 4 years ago

Thank you Sara; I have read documentation; just not sure I have a full grasp of all the details, also have gone thru the open and closed issues.  Posted my issue on the github library page.

 

request->send_P(200, PSTR(“text/html”), HTML6, processor6);

Other two requests in the “notFound” fuction commented out; produces a web page with header and hyperlink and a mirror of the header and hyperlink, but no text.  I beleve this is due to not having the filename returned at this point in the “notFound” function.

Here is what I have so far:

Start your code here

serverAsync.on(“/SdBrowse”, HTTP_GET, [](AsyncWebServerRequest * request)
{

PATH = “/SdBrowse”;
accessLog();
if (! flag == 1)
{

request->send_P(200, PSTR(“text/html”), HTML2, processor2);

}
end();

});
serverAsync.on(“/Show”, HTTP_GET, [](AsyncWebServerRequest * request)
{

PATH = “/Show”;
accessLog();
if (! flag == 1)
{

request->send_P(200, PSTR(“text/html”), HTML6, processor6);

}
end();
});


“/Show” request only works after “/SdBrowse” request has processed the selected url thru the above posted “notFound” function; when this happens, “/Show” request displays header, text file with scroll bar, and hyperlink to return to “/SdBrowse” list of “LOG” files..

if “/Show” request is made before “/SdBrowse” request; only header and hyperlink are displayed, no text file is displayed.

Trying to show web page with header, text file, and hyperlink; on selection of the filename in the “SdBrowser” request.

Best Regards,
William

0 Vote Up Vote Down
William Lucid answered 4 years ago

Short under 3 minute, video of what I have completed so far…
Video: adding hyperlink to text.txt file.
RainGauge project link…
William

0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi William.
Thanks for sharing the resources to your project. 
It seems that the processor() function for that HTML6 is not working at the right time, or it doesn’t have enough time to send all the data to be replaced in the processor() function.
Can you show me the processor6() function? Does it seem the problem can be there?
Regards,
Sara

0 Vote Up Vote Down
William Lucid answered 4 years ago

Hi Sara,

Do I need to pass the uncfn variable to:

“serverAsync.on(“/Show”, HTTP_GET, [](AsyncWebServerRequest * request)”?  Acts like it is not getting the filename.

HTML6 processor 6:

Start your code here

String processor6(const String& var)
{

//index6.h

if (var == F(“LINK”))
return linkAddress;

if (var == F(“UNCFN”))
return uncfn;

return String();

}

William

0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi again.
In your HTML6 file, can you remove the following the width=”100%”:

<br> <div><object data=http://%LINK%/%UNCFN% width=”100%” height=”700″></object></div>

So, it looks as follows:

<br> <div><object data=http://%LINK%/%UNCFN%  height=”700″></object></div>

Let me know if that solves the issue.
Regards,
Sara
 

0 Vote Up Vote Down
William Lucid answered 4 years ago

Good Morning,

Edited following line:

"<br> <div><object data=http://%LINK%/%UNCFN%  height=”700″></object></div>"

Only change was a smaller text “window” on the left.

Made other changes and have confirmed filename is being passed. The notFound request is expecting a response; client side “somehow” displays a “text/plain”

text screen.  If a “/path/Show” request is made; HTML6, processor6 display Web page with header, embedded text file, and hyperlink.

 

“/Show” request changes:

Commented out “/Show” request.

notFound function changes:

String notFound(AsyncWebServerRequest *request)
{

if (! request->url().endsWith(F(“.TXT”)))
{
request->send(404);
}
else
{
if (request->url().endsWith(F(“.TXT”)))
{
//.endsWith(F(“.txt”)))

// here comes some mambo-jambo to extract the filename from request->url()
int fnsstart = request->url().lastIndexOf(‘/’);

fn = request->url().substring(fnsstart);

uncfn = fn.substring(1);

}

}

request->send_P(200, PSTR(“text/html”), HTML6, processor6);

}

HTML6:

//index6.h
const char HTML6[] PROGMEM = R”====(
<!DOCTYPE HTML>
<html>

<head>
<title>Show</title>
</head>

<body>
<h2>Collected Observations
<br>
<br> <div><object data=http://%LINK%/%UNCFN% type=”text\html” width=”100%” height=”700″></object></div>
<br>
<br>
<a href=http://%LINK%/SdBrowse >SdBrowse</a></h2><br>
</body>

</html>
)====”;

processor6:

String processor6(const String& var)
{

//index6.h

if (var == F(“LINK”))
return linkAddress;

if (var == F(“UNCFN”))
return uncfn;

return String();

}


William

0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi again.
 
The reason why I told you to remove that line is because % signs other than the placeholders % signs might cause issues with the processor function. That’s why I thought that could be causing the issue.
 
Is it working with your new changes?
 
Regards,
Sara

0 Vote Up Vote Down
William Lucid answered 4 years ago

Good Morning Sara,

Still not working as designed; have to display log file twice to be able to display HTML6, web page.  First display is plain text; addtess in “Chrome” browser, “http://externalip/filename.”  Second log text  file has both “Header” and “Hyperlink’ using “text/html.”  Displaying twice is the same log file; address in “Chrome” is “http://externalip/Show”&#8221; why I moved sending, the response for “HTML6, processor6” line to the “notFound” function.  I have no SPIFFS file statements  and no SPIFFS “request->send”; yet “Chrome” displays log file in “text/plain” text.

I am able to see correct “text” box area with width=”100%”; without the width=100%,” “text” box area where log file is displayed is much smaller.  Thank you for suggest trying to remove width=100%.

William

0 Vote Up Vote Down
William Lucid answered 4 years ago

How do you use “Espasyncwebserver,” request->send_P(200, PSTR(“text/html”), HTML, processor) with a HTML object data attribute, calling “LOG.TXT” from spiffs?

Sara, thanks for suggestion of removing “width=100%”; this and a bad url path were keeping text from being displayed,  Today’s code (07/07/2021) still does not go from file name selection to display of the LOG file with a HTML Header, text box with scroll bar, and a Hyperlink at the bottom of the page to return to list of files.  So, the same LOG file is display twice; once with plain text, and onec as Web page.

“RainGauge.zip” project code

Project website

Viewing the HTML Log file on the project website requires selecting “File Browser” first; then use the back browser arrow and select “Show Log File.”

William



0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi.

The best way to do that is using JavaScript.

I’ve created a simple example. I hope you can understand it and use the concepts in your project.
This example:

  1. Shows a main web page with a button “Show”. When you click the button it makes a request on the /show URL.
  2. The ESP32 receives that request and sends the HTML to display the web page on the /show URL.
  3. The SHOW web page displays some HTML from the index_html_2 file. This file calls a file from spiffs with data called data.txt. –> So, this page calls a file from SPIFFS as you asked. The easiest way to do this is using JavaScript.

Here’s how it works:
When the SHOW page loads, a JavaScript function called getFile() runs. The getFile() function makes a request on the /get-file URL.

function getFile(){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      console.log(this.responseText);
      document.getElementById("file-content").innerHTML=this.responseText;
    }
  };
  xhr.open("GET", "/get-file", true);
 xhr.send();
}

When the ESP32 receives that request, it sends the corresponding file that is saved in SPIFFS (data.txt file);

server.on("/get-file", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(SPIFFS, "/data.txt", "text/txt");
});

The web page, receives the content of that file and places it on the HTML page on the paragraph with the “file-content” id:

if (this.readyState == 4 && this.status == 200) {
  console.log(this.responseText);
  document.getElementById("file-content").innerHTML=this.responseText;
}

You can see the complete example here: https://gist.github.com/sarasantos/e3bef253c34109f7f76fb6e0be38f862

I hope this helps.
Regards,
Sara

0 Vote Up Vote Down
William Lucid answered 4 years ago

Javascript is working as written, Thank you Sara!  One remaining issue relating to text all “running” together.

HTML6, document that adds Header, text file, and Hyperlink returning to list of url filename requests.

HTML6:

Start your code here

//index6.h
const char HTML6[] PROGMEM = R”====(
<!DOCTYPE HTML>
<html>
<head>
<title>Show</title>
<style>
.main
{
type: text/csv;
font-size:14px;
width: auto;
height: auto;
margin: 30px;
}
</style>
</head>
<body>
<h2>Observations
<!– <a href=”/Show”><button>Show Log File</button></a> –>
<br>
<br>
<div class=”main” id=file-content></div>
<br>
<a href=http://%LINK%/SdBrowse >SdBrowse</a></h2><br>

</body>
<script>  //Sara’s JavaScript example
window.addEventListener(‘load’, getFile);
function getFile(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
document.getElementById(“file-content”).innerHTML=this.responseText;
}
};
xhr.open(“GET”, “/get-file”, true);
xhr.send();
}
</script>
</html>
)====”;

Processor2:

Start your code here

String processor2(const String& var)  //creates list of url hyperlinks of filename in root directory
{                                                           //processed by the notFound function.
  //index2.h
  String str;
  File root = SPIFFS.open(“/”);
  root.rewindDirectory();  //added 6/17/2021
  File file = root.openNextFile();

  //file.seek(0, SeekSet);
  while (file)
  {
    if (strncmp(file.name(), “/LOG”, 4) == 0)
    {

      str += “<a href=\””;
      str += file.name();
      str += “\”>”;
      str += file.name();
      str += “</a>”;
      str += ”    “;
      str += file.size();
      str += “<br>\r\n”;
    }
    file = root.openNextFile();
  }
  root.close();
  root.rewindDirectory();
  if (var == F(“URLLINK”))
    return  str;
  if (var == F(“LINK”))
    return linkAddress;
  if (var == F(“FILENAME”))
    return  file.name();
  return String();
}

—————–
“GET” requests “/Show”:

Start your code here

serverAsync.on(“/Show”, HTTP_GET, [](AsyncWebServerRequest * request)
{

PATH = “/Show”;
accessLog();
if (! flag == 1)
{

request->send_P(200, PSTR(“text/html”), HTML6, processor6);

}
end();
});

——-
“GET” request “/get-file”:

Start your code here

serverAsync.on(“/get-file”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, fn, “text/html”);
});

————-

“notFound” function

Start your code here

String notFound(AsyncWebServerRequest *request)  //Code from a “Github” formum member.
{
digitalWrite(online, HIGH);   //turn-on online LED indicator
if (! request->url().endsWith(F(“.TXT”)))
{
request->send(404);
}
else
{
if (request->url().endsWith(F(“.TXT”)))
{
//.endsWith(F(“.txt”)))
// here comes some mambo-jambo to extract the filename from request->url()
int fnsstart = request->url().lastIndexOf(‘/’);
fn = request->url().substring(fnsstart);
uncfn = fn.substring(1);
urlPath = linkAddress + “/” + uncfn;
}
}
request->redirect(“/redirect/internal”);
digitalWrite(online, LOW);   //turn-off online LED indicator
return fn;
}

—————

“GET” request for redirect:

Start your code here

serverAsync.on(“/redirect/internal”, HTTP_GET, [](AsyncWebServerRequest *request){
request->redirect(“/Show”);  //recieced HTML status 302 code
});

William

0 Vote Up Vote Down
William Lucid answered 4 years ago

Sara,
Could you implement this with your JavaScript example, please?

File API – FileReader (Text) –Fiddle meta

Looks promising:

File API – FileReader (Text) –image –“LOG07112021.TXT”

I do not have the skill set to implement.  Will have to learn to write JavaScript…
at 73 years old, might take awhile.

Best Regards,
William

0 Vote Up Vote Down
William Lucid answered 4 years ago

Sara found a better solution:

To solve that issue you can add the following styling to the paragraph that displays the data:

white-space: pre-wrap;

So, instead of this,
<p style width=”1600″; height=”700″; id=”file-content”><p> <======Note this styling did not help much.

You would have something like this:

<p style=”white-space: pre-wrap;”id=”file-content”></p>

I found this suggestion here: https://stackoverflow.com/questions/40417527/how-do-i-preserve-line-breaks-when-getting-text-from-a-textarea/40426477

Now; log files have header, text area and hyperlink!

Check out project web site…

William

0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

That’s great!
Can I close this issue?
Regards,
Sara

0 Vote Up Vote Down
William Lucid answered 4 years ago

Sounds good; you may close this issue.
Thanks!!!
William

Primary Sidebar

Login to Ask or Answer Questions

This Forum is private and it’s only available for members enrolled in our Courses.

Login »

Latest Course Updates

  • [eBook Updated] Learn Raspberry Pi Pico/Pico W with MicroPython eBook – Version 1.2 May 26, 2025
  • [New Edition] Build ESP32-CAM Projects eBook – 2nd Edition April 16, 2025

You must be logged in to view this content.

Contact Support - Refunds - Privacy - Terms - MakerAdvisor.com - Member Login

Copyright © 2013-2025 · RandomNerdTutorials.com · All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.