概要
ESP32にsoftAP機能とAsyncwebserverを実装して、非同期Webサーバとして運用しています
ESP32はSPIFFSファイルシステムを利用しており、HTMLなどの静的ファイルやログcsvなどの動的ファイルが保存されています
実現したいこと
クライアント側 Web画面上からの操作でSPIFFS内のログcsvをダウンロード(PC側に保存)したいです
ただ、ログcsvは動的に生成されるためあらかじめファイル名が決まっておらず、server.onでファイル名にアクセスされた時の動作を規定するAsyncwebserverの一番簡単な方法が使えずに困っています
問題点
オーソドックスにSPIFFS内に保存されたファイルをWebページ上からダウンロードしようと思ったら、下記の様になりますよね
HTML
1<a href="/log/test.csv">dammy.csv</a>
Arduino
1server.on("/log/test.csv", HTTP_GET, [](AsyncWebServerRequest *request){ 2 request->send(SPIFFS, "/log/test.csv", "text/csv"); 3 delay(1) ; 4 });
しかし、上記例では試験的にあらかじめ用意したtest.csvという名前のファイルをダウンロードするだけだからいいですが、実際にはログは動的に生成され、ファイル名が都度変わります
ファイル名が事前に決まっていないとserver.onの待ち受けアドレス(最初の引数)でファイル名にアクセスされるのを待ち受ける形にはできません
試したこと
a hrefを使うのではなく、クライアント側からダウンロードしたいファイルのパスをFormDataに含んだPOSTを発出し、POSTを受けてサーバ側が関数を呼び出し、該当のパスのファイルをレスポンスとしてクライアント側に返すようにしてみましたが、何の反応もありません。
レスポンスがうまくできていないのか、もしくはレスポンス自体は帰っているけど、クライアント側が「これはダウンロードするデータだ」と認識していなくてスルーしているのか分かりませんが…javascript側にレスポンスを待ち受ける記述が必要なのでしょうか…
HTML
1<input id="path_input" type="text" name="path_input"><br> 2<button id="path" type="button" name="path" form="path_input" value="form_value" onclick="POST_event(this);">DOWNLOAD</button>
JavaScript
1function POST_event(ele) 2 { 3 var formID = ele.getAttribute("form"); 4 var buttonNAME = ele.getAttribute("name"); 5 var buttonVALUE = document.getElementById(formID).value; 6 7 var XHR = new XMLHttpRequest(); 8 var postDatas = new FormData(); 9 postDatas.append(buttonNAME, buttonVALUE); 10 XHR.open("POST", "/POST_Receiver", true); 11 XHR.send(postDatas); 12 }
Arduino
1// POST解析&処理 2 server.on("/POST_Receiver", HTTP_POST, [](AsyncWebServerRequest *request) { 3 int params = request->params(); 4 for(int i=0;i<params;i++) 5 { 6 AsyncWebParameter* p = request->getParam(i); 7 String name = p->name().c_str(); 8 String value = p->value().c_str(); 9 if( name == "path" ){AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/test.csv", "text/csv"/*value.c_str(), String(), true*/); request->send(response);} 10 } 11 delay(1) ; 12 });
要約
実現したいことは、動的に生成される、あらかじめファイル名が定まっていないログファイルを、クライアント側にダウンロードしたい、ということです
「試したこと」の方向性自体が間違っているのか、それとも方向性は合っているけど記述が不足している、間違っているのか
他にこのような方法があるんじゃないのか、などアドバイスいただけると嬉しいです
追記
今、一つパッと思いついたのですが、server.onNotFoundで指定されたパスのファイルがSPIFFS内に存在するかlistDirで検索して、一致した場合にそのファイルをrequest->sendすれば、a herfやJavaScriptのlocation.replace(link);でダウンロードできるかも…
それと、参考にしている(というか本家の)ページにこんな記述がありました。
https://github.com/me-no-dev/ESPAsyncWebServer#file-upload-handling
Arduino
1// save callback for particular URL path 2auto handler = server.on("/some/path", [](AsyncWebServerRequest *request){ 3 //do something useful 4});
これを使って、/log以下にアクセスされたときに起動するハンドラーが作れたりしないかなぁ…
本日は他の作業をやらなくてはならず時間がないため、検証は来週に行うことにします…
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/10/11 00:17
2021/10/11 08:00
2021/10/11 09:28
2021/10/11 11:39
2021/10/12 09:46