Add file list, delete and download in ESP32 simple file server - c++

It's the first time to ask a question, please forgive me if I am wrong.
English is not my native language; please excuse typing errors.
I am using ESP32 for the first time. I want to be a file server, but now it only has upload function. I want to add download, delete and file list. I have not been able to find suitable information. thank you.
ESP32 code:
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <SPI.h>
#include <SPIFFS.h>
void setup() {
Serial.begin(115200);
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
}
start_access_point();
start_web_server();
}
void loop()
{
}
const char* ap_ssid = "ESP32";
const char* ap_pwd = "12345678";
void start_access_point(){
WiFi.softAP(ap_ssid, ap_pwd);
IPAddress myIP = WiFi.softAPIP();
Serial.println("Access point started");
Serial.print("AP IP address: ");
Serial.println(myIP);
}
AsyncWebServer server(80);
const char* PARAM_SSID = "ssid";
const char* PARAM_PWD = "pwd";
void start_web_server(){
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});
server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){
if(request->hasArg("file")){
String fileName = request->arg("file");
File f = SPIFFS.open("/data/fileName", "w");
if(!f){
request->send(500, "text/plain", "Could not open file for writing");
return;
}
std::string fileData = std::string(request->arg("file").c_str());
f.write((uint8_t*)fileData.c_str(), fileData.length());
f.close();
request->send(200, "text/plain", "File uploaded successfully");
}
else{
request->send(500, "text/plain", "No file data found in request");
}
});
server.begin();
}
HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>.app-container{
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
h3{
text-align: center;
color: #5a5c69 !important;
font-family: Arial, Helvetica, sans-serif;
}
/* Style inputs, select elements and textareas */
input[type=text], select, textarea{
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
resize: vertical;
}
input[type=password], select, textarea{
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
resize: vertical;
}
/* Style the label to display next to the inputs */
label {
padding: 12px 12px 12px 0;
display: inline-block;
}
/* Style the submit button */
input[type=submit] {
background-color: #4CAF50;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
float: right;
}
/* Floating column for labels: 25% width */
.col-25 {
float: left;
width: 25%;
margin-top: 6px;
}
/* Floating column for inputs: 75% width */
.col-75 {
float: left;
width: 75%;
margin-top: 6px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */
#media screen and (max-width: 600px) {
.col-25, .col-75, input[type=submit] {
width: 100%;
margin-top: 0;
}
}
</style>
<title id="apptitle">Setup Wifi</title>
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
Download file
</body>
</html>
I tried to find a similar function modification on github, but there was no way

List. Simple iteration through all files in the data folder of esp32. Absolute path deletion before file name has to be done manually if you just want the file names:
#include "SPIFFS.h"
void setup() {
Serial.begin(115200);
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
File root = SPIFFS.open("/");
File file = root.openNextFile();
while(file){
Serial.print("FILE: ");
Serial.println(file.name());
file = root.openNextFile();
}
}
void loop() {}
Delete:
SPIFFS.remove(path); (all paths are absolute paths)
exists function to check if file exists
mkdir creating new folder
rmdir remove folder
opendir
rename
info
and more can be found here. just scroll down enough until you find them in the documentation:
https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
Edit: Forgot to add download here. Download can be accomplished similarly to what you already have for your API:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});
It could send you to a new tab with the new link and use the response as a download buffer type thing. But change the type to the type of file you want. Im not quite sure what the name of the type was but i think it was something on the line of "binary/png" or something. you'd have to search that up

Related

Play sound when image tracking is on with AR.js

I just want to play the mp3 when the image tracking is turned on, and stop the sound
What currently works is that after recognizing the nft, the model comes out well
but the sound doesn't play
Play and pose sound when image tracking is on with AR.js
I used the code in this link, but it doesn't seem to work due to my lack of skills
The link was intentionally deleted (a-assets,a-nft,a-entity)
please give me any advice. Thanks
'''
<script>
AFRAME.registerComponent('soundhandler', {
tick: function () {
var entity = document.querySelector('sound');
if (document.querySelector('a-nft').object3D.visible == true) {
entity.components.sound.playSound();
} else {
entity.components.sound.pauseSound();
}
}
});
</script>
<style>
.arjs-loader {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.8);
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
.arjs-loader div {
text-align: center;
font-size: 1.25em;
color: white;
}
</style>
<body style="margin: 0px; overflow: hidden">
<!-- minimal loader shown until image descriptors are loaded -->
<div class="arjs-loader">
<div>Loading, please wait...</div>
</div>
<a-scene
cursor="rayOrigin: mouse"
vr-mode-ui="enabled: false;"
renderer="logarithmicDepthBuffer: true; precision: medium;"
embedded arjs="trackingMethod: best; sourceType: webcam;debugUIEnabled: false;"
gesture-detector
id="scene"
>
<a-assets>
<a-asset-item src="https.mp3"
preload="false" id="sound" response-type="arraybuffer" loop
crossorigin webkit-playsinline autoplay="false" playsinline>
</a-asset-item>
</a-assets>
<!-- we use cors proxy to avoid cross-origin problems ATTENTION! you need to set up your server -->
<a-nft
type="nft"
url="https:rogoqr"
smooth="true"
smoothCount="10"
smoothTolerance=".01"
smoothThreshold="5"
raycaster="objects: .clickable"
emitevents="true"
cursor="fuse: false; rayOrigin: mouse;"
>
<a-sound src="#sound"></a-sound>
<a-entity
gltf-model="https:.glb"
scale="2 2 2"
position="100 -20 -115"
class="clickable"
gesture-handler="minScale: 0.25; maxScale: 10"
sound="src: #sound" autoplay="false"
>
</a-entity>
</a-nft>
<a-entity camera></a-entity>
</a-scene>
<script>
</script>
</body>
'''
please give me any advice. Thanks

How can I 'if' condition in docment.getElementById.style.background?

.div_wrap_p_bestgames {
display: table;
width: 130px;
height: 40px;
float: left;
background: #1B1C1E;
position: relative;
margin-top: 150px;
margin-left: -100px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
this is css code.
I want to set div_wrap_p_bestgames's mouseout function
if condition with background color #1B1C1E
function onMouseoutNewGames() {
if (document.getElementById("div_wrap_p_newgames").style.background == "#1B1C1E")
///do something
}
this condition is not working
You will need to use the below line to get the background color of an element
document.getElementById("div_wrap_p_newgames").style.backgroundColor
if you need to compare this with a specific value, convert your hex code to a rgb value and compare it as such,
if(document.getElementById("myDiv").style.backgroundColor == "rgb(27, 28, 30)")
rgb(28,27,30) is the equivalent of #1B1C1E
<!DOCTYPE html>
<html>
<body>
<h1>Hello World!</h1>
<div id="myDiv" style="background-color:#1B1C1E;">This is a div element.</div>
<br>
<button type="button" onclick="myFunction()">Get the background color of div</button>
<script>
function myFunction() {
if(document.getElementById("myDiv").style.backgroundColor == "rgb(27, 28, 30)")
{
alert("hi");
}
}
</script>
</body>
</html>
Works fine when I try it.

How to change font size and other style of jqgrid 4.15

Trying to update look and feel of jqgrid.
I am trying to increase the font size of the data in the grid as well as of the column header.
Here is my jsfiddle
https://jsfiddle.net/4ga1ekh3/69/
Using the code at
How to change the font size in jqGrid?
.ui-jqgrid {font-size:0.8em}
But this did not work.
I would also like to know how to increase the font of the various fields when of the edit form
Since no one answered here, I resolved this by using the below code:
.ui-jqgrid tr.jqgroup td {
font-weight: bold;
font-size: 12px;
}
.ui-jqgrid .ui-th-column > div.ui-jqgrid-sortable {
font-size: 15px;
}
span.ui-jqgrid-cell-wrapper {
font-size: 16px;
}
td.jqgrid-rownum {
font-size: 15px;
}

Scrollable Foundation Section headers

Looking through http://foundation.zurb.com/docs/components/section.html, is there anyway I can add horizontal scroll for Section headers ( Tabs) . I am looking something like http://www.seyfertdesign.com/jquery/ui.tabs.paging.html in foundation sections with horizontal scroll and continue to use accordion in small screen
I found a solution for those interested : https://codepen.io/gdyrrahitis/pen/BKyKGe
.tabs {
overflow-x: auto;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
.tabs-title {
float: none;
display: inline-block;
}
}
if someone needs an angularjs with jquery implementation, below code can help you, for pure jquery replace angularjs directive method with a native js method with respective attributes.
I tried to search for similar implementation but found nothing, so I have written a simple angular directive which can transform a foundation CSS tabs to scrollable tabs
angular.module("app.directives.scrollingTabs", [])
.directive("scrollingTabs", ScrollingTabsDirective);
//#ngInject
function ScrollingTabsDirective($timeout, $window) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if(attr.scrollingTabs == "true"){
element.addClass('scrolling-tabs-container');
element.find('.nav-buttons').remove();
element.append('<div class="scrolling-tabs nav-buttons nav-buttons-left"></div>');
element.append('<div class="scrolling-tabs nav-buttons nav-buttons-right"></div>');
let scrolledDiv = $(element).find('.tabs');
let scrolled;
let scrolling;
let scrollFn = (step, animationTime, cb) => {
scrolled = Math.max(scrolled + step, 0);
scrolledDiv.animate({
scrollLeft: scrolled
}, animationTime, ()=>{
if (scrolling) {
scrollFn(step, animationTime, cb)
}else{
if(cb){cb()}
}
});
};
let checkActiveNavButtonsClasses = () => {
scrolled = scrolledDiv.scrollLeft();
let scrollWidth = scrolledDiv.get(0).scrollWidth;
let scrolledDivWidth = scrolledDiv.get(0).clientWidth;
if(scrollWidth > scrolledDivWidth){
element.addClass('nav-active');
scrollWidth = scrolledDiv.get(0).scrollWidth;
if(scrolled == 0){
element.removeClass('nav-active-left').addClass('nav-active-right')
}else if(scrolled > 0 && scrolled + scrollWidth < scrolledDivWidth){
element.addClass('nav-active-left').addClass('nav-active-right');
}else if(scrolled > 0 && scrolled + scrollWidth >= scrolledDivWidth){
element.addClass('nav-active-left').removeClass('nav-active-right');
}else{
element.removeClass('nav-active-left').removeClass('nav-active-right')
}
}else{
element.removeClass('nav-active-left').removeClass('nav-active-right').removeClass('nav-active');
}
};
let scrollToActiveTab = () => {
let activeDD = scrolledDiv.find('dd.active');
let tabsOffset = scrolledDiv.offset();
let activeTaboffset = activeDD.offset();
let activeTabwidth = activeDD.width();
let scrolledStep = activeTaboffset.left - tabsOffset.left - scrolledDiv.width() + activeTabwidth;
scrollFn(scrolledStep, 100, checkActiveNavButtonsClasses);
};
element.find(".nav-buttons.nav-buttons-left")
.off("click.scrolling")
.on("click.scrolling", (event)=>{
event.preventDefault();
scrolling = false;
scrollFn(-100, 100, checkActiveNavButtonsClasses);
})
.off("mouseover.scrolling")
.on("mouseover.scrolling", function (event) {
scrolling = true;
scrollFn(-2, 1, checkActiveNavButtonsClasses);
})
.off("mouseout.scrolling")
.on("mouseout.scrolling", function (event) {
scrolling = false;
});
element.find(".nav-buttons.nav-buttons-right")
.off("click.scrolling")
.on("click.scrolling", (event)=>{
event.preventDefault();
scrolling = false;
scrollFn(100, 100, checkActiveNavButtonsClasses);
})
.off("mouseover.scrolling")
.on("mouseover.scrolling", function (event) {
scrolling = true;
scrollFn(2, 1, checkActiveNavButtonsClasses);
})
.off("mouseout.scrolling")
.on("mouseout.scrolling", function (event) {
scrolling = false;
});
$timeout(()=>{
checkActiveNavButtonsClasses();
scrollToActiveTab()
},1000);
$($window).off('resize.scrolling').on('resize.scrolling', _.debounce(()=> {
checkActiveNavButtonsClasses();
}, 500));
scope.$on('$destroy', function() {
$($window).off('resize.scrolling');
});
}
}
}}
css:
.scrolling-tabs-container {
position: relative;
.tabs {
overflow-x: hidden;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
display: block;
margin-right: 18px;
dd {
display: inline-block;
float: none;
margin: 0px -3px 0px 0px;
}
.tabs-title {
float: none;
display: inline-block;
}
}
.scrolling-tabs {
&.nav-buttons {
display: none;
position: absolute;
width: 19px;
height: 38px;
border: 1px solid #c1c1c1;
top: 1px;
background-color: rgba(255, 255, 255, 0.5);
opacity: 0.4;
cursor: pointer;
&:hover {
opacity: 1;
&:before {
color: #444;
}
}
&:before {
position: absolute;
left: 7px;
top: 8px;
color: #777;
}
&.nav-buttons-left {
left: 0;
&:before {
content: '<';
}
}
&.nav-buttons-right {
right: 18px;
&:before {
content: '>';
}
}
}
}
&.nav-active{
.tabs{
margin-right: 36px;
margin-left: 18px;
}
.scrolling-tabs {
&.nav-buttons {
display: inline-block !important;
}
}
}
&.nav-active-left{
.scrolling-tabs{
&.nav-buttons-left{
opacity: 0.8;
}
}
}
&.nav-active-right{
.scrolling-tabs{
&.nav-buttons-right{
opacity: 0.8;
}
}}}
HTML: Foundation Tabs template.
<tabset class="list-tabs" scrolling-tabs="true">
<tab heading="tab1"></tab>
<tab heading="tab2"></tab>
<tab heading="tab2"></tab>
</tabset>
Before you start you'll want to verify that both jQuery (or Zepto) and foundation.js are available on your page. These come with foundation package so just uncomment them in your footer or include them accordingly.
<div class="section-container auto" data-section>
<section class="active">
<p class="title" data-section-title>Section 1</p>
<div class="content" data-section-content>
<p>Content of section 1.</p>
</div>
</section>
<section>
<p class="title" data-section-title>Section 2</p>
<div class="content" data-section-content>
<p>Content of section 2.</p>
</div>
</section>
</div>
The foundation documentation has all of the information for this :
http://foundation.zurb.com/docs/components/section.html#panel2
This will get you your section tabular headers. You then want to manage the content to be scrollable.
<div class="content" data-section-content>
<p>Content of section 1.</p>
</div>
This content here will be the area to work on, try adding a new class called .scrollable
Within this class use something like:
.scrollable{
overflow:scroll;
}
You may want to add some more to this however this will get you started. Your HTML should now look like this :
<div class="content scrollable" data-section-content>
<p>Content of section 1. This content will be scrollable when the content has exceeded that of the div size. </p>
</div>
This this is what you are looking for.

selected list item in MVC 2.0

i inherited a menu based on lists that was used before i started and that needs going into MVC.
The list needs to show a white box for the selected item and a standard grey box for the rest. up to now, all that gets shown is a grey box for all. We have been looking around for a solution for this but we fail to get to the bottom to this. The list would be extended as time goes by
<ul id="headerBarMenu" class="horizontalMenu">
<li class="fontstyle01a" >
<%: Html.ActionLink("Manage Payment Run", "ManagePaymentRun", "Home")%></li>
<li class="fontstyle01a" >
<%: Html.ActionLink("About", "About", "Home")%></li>
</ul>
ul.horizontalMenu li
{
list-style: none;
padding: 0;
float: left;
border-top: 1px solid #bbb;
border-right: 1px solid #bbb;
border-bottom: 0px;
border-left: 1px solid #bbb;
margin: 0;
}
ul.horizontalMenu a
{
padding: .6em 1.5em 1em 1.5em;
display: block;
background: #cccccc;
}
ul.horizontalMenu a.selected
{
position: relative;
top: 1px;
background: white;
color: black;
font-weight: bold;
}
.fontstyle01a /*bold_dark*/
{
font-family: Verdana, Arial, Helvetica, sans-serif;
text-align: center;
font-size: 7pt;
font-style: normal;
font-weight: bold;
color:#666666;
text-decoration: none;
margin: 0;
padding: 0;
width: 140px;
}
.fontstyle01a a, a:link, a:visited
{
color:#666666;
text-decoration: none;
}
.fontstyle01a a:activea:hover
{
color:#9f117a;
}
Ive been looking at the following to try and change it this, but i have not yet found a solution.
Thanks for the time
Here's a html helper method you might try. It sets the classname based on the current action:
public class Link
{
public string Text { get; set; }
public string Action { get; set; }
public string Controller { get; set; }
public object RouteValues { get; set; }
public object HtmlAttributes { get; set; }
}
public static class HtmlExtensions
{
public static MvcHtmlString Menu(this HtmlHelper htmlHelper, IEnumerable<Link> links)
{
var currentAction = (string)htmlHelper.ViewContext.RouteData.Values["action"];
var currentController = (string)htmlHelper.ViewContext.RouteData.Values["controller"];
var ul = new TagBuilder("ul");
ul.GenerateId("headerBarMenu");
ul.AddCssClass("horizontalMenu");
links = links ?? Enumerable.Empty<Link>();
var sb = new StringBuilder();
foreach (var link in links)
{
var li = new TagBuilder("li");
if (string.Equals(currentAction, link.Action, StringComparison.OrdinalIgnoreCase) &&
string.Equals(currentController, link.Controller, StringComparison.OrdinalIgnoreCase))
{
li.AddCssClass("white");
}
else
{
li.AddCssClass("grey");
}
li.InnerHtml = htmlHelper.ActionLink(link.Text, link.Action, link.Controller, link.RouteValues, link.HtmlAttributes).ToHtmlString();
sb.Append(li.ToString());
}
ul.InnerHtml = sb.ToString();
return MvcHtmlString.Create(ul.ToString());
}
}
And then apply the menu in your views:
<%= Html.Menu(new[] {
new Link { Text = "Manage Payment Run", Action = "ManagePaymentRun", Controller = "Home" },
new Link { Text = "About", Action = "About", Controller = "Home" },
}) %>
Now if you navigate to /home/ManagePaymentRun the first li will get the class white and if you navigate to /home/about the second li will get this class.
All that is left now is to style those rules:
.white {
/** TODO **/
}
.grey {
/** TODO **/
}
Check out this answer to one of my questions. It is a HtmlHelper that returns a class name based on controller and/or action.