diff --git a/htdocs/css/files.css b/htdocs/css/files.css
new file mode 100644
index 00000000..b9b77d78
--- /dev/null
+++ b/htdocs/css/files.css
@@ -0,0 +1,29 @@
+@import url("openwebrx-header.css");
+@import url("openwebrx-globals.css");
+
+html, body {
+ height: unset;
+}
+
+body {
+ margin-bottom: 5rem;
+}
+
+hr {
+ background: #444;
+}
+
+h1 {
+ margin: 1em 0;
+ text-align: center;
+}
+
+table {
+ border-collapse: separate;
+ border-spacing: 15px;
+}
+
+td {
+ text-align: center;
+ border: 3px dotted;
+}
diff --git a/htdocs/css/openwebrx.css b/htdocs/css/openwebrx.css
index 6fb6e2ed..a55a109d 100644
--- a/htdocs/css/openwebrx.css
+++ b/htdocs/css/openwebrx.css
@@ -158,8 +158,8 @@ input[type=range]:disabled {
{
height: 100%;
position: relative;
- display: flex;
- flex-direction: column;
+ display: flex;
+ flex-direction: column;
}
#openwebrx-scale-container
diff --git a/htdocs/files.html b/htdocs/files.html
new file mode 100644
index 00000000..0125d0f4
--- /dev/null
+++ b/htdocs/files.html
@@ -0,0 +1,18 @@
+
+ OpenWebRX+ Received Files
+
+
+
+
+
+
+
+
+ ${header}
+
+
OpenWebRX+ Received Files
+
+
+
diff --git a/htdocs/files.js b/htdocs/files.js
new file mode 100644
index 00000000..a663729f
--- /dev/null
+++ b/htdocs/files.js
@@ -0,0 +1,17 @@
+function saveCanvas(canvas, name) {
+ var a = document.createElement('a');
+
+ canvas.toBlob(function(blob) {
+ a.href = window.URL.createObjectURL(blob);
+ }, 'image/png');
+
+ a.style = 'display: none';
+ a.download = name;
+ document.body.appendChild(a);
+ a.click();
+
+ setTimeout(function() {
+ document.body.removeChild(a);
+ window.URL.revokeObjectURL(a.href);
+ }, 0);
+}
diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js
index 825a2a85..aa23ffce 100644
--- a/htdocs/openwebrx.js
+++ b/htdocs/openwebrx.js
@@ -93,6 +93,24 @@ function toggleRecording() {
}
+function saveCanvas(canvas, name) {
+ var a = document.createElement('a');
+
+ canvas.toBlob(function(blob) {
+ a.href = window.URL.createObjectURL(blob);
+ }, 'image/png');
+
+ a.style = 'display: none';
+ a.download = name;
+ document.body.appendChild(a);
+ a.click();
+
+ setTimeout(function() {
+ document.body.removeChild(a);
+ window.URL.revokeObjectURL(a.href);
+ }, 0);
+}
+
function zoomInOneStep() {
zoom_set(zoom_level + 1);
}
diff --git a/owrx/controllers/file.py b/owrx/controllers/file.py
new file mode 100644
index 00000000..0589693d
--- /dev/null
+++ b/owrx/controllers/file.py
@@ -0,0 +1,62 @@
+from owrx.controllers.template import WebpageController
+from owrx.controllers.assets import ModificationAwareController
+from owrx.breadcrumb import Breadcrumb, BreadcrumbItem, BreadcrumbMixin
+from owrx.controllers.settings import SettingsBreadcrumb
+from owrx.config.core import CoreConfig
+
+from datetime import datetime, timezone
+import mimetypes
+import os
+import re
+
+class FileController(ModificationAwareController):
+ def getModified(self, file):
+ return datetime.fromtimestamp(os.path.getmtime(file), timezone.utc)
+
+ def openFile(self, file):
+ return open(file, "rb")
+
+ def serve_file(self, file, content_type=None):
+ try:
+ modified = self.getModified(file)
+
+ if not self.wasModified(file):
+ self.send_response("", code=304)
+ return
+
+ f = self.openFile(file)
+ data = f.read()
+ f.close()
+
+ if content_type is None:
+ (content_type, encoding) = mimetypes.guess_type(file)
+ self.send_response(data, content_type=content_type, last_modified=modified, max_age=3600)
+ except FileNotFoundError:
+ self.send_response("file '%s' not found" % file, code=404)
+
+ def indexAction(self):
+ filename = self.request.matches.group(1)
+ self.serve_file("/tmp/" + filename)
+
+
+class FilesController(WebpageController):
+ def template_variables(self):
+ files = [f for f in os.listdir('/tmp') if re.match(r'SSTV-[0-9]+-[0-9]+\.bmp', f)]
+ rows = ""
+
+ for i in range(len(files)):
+ # Start a row
+ if i % 3 == 0:
+ rows += '\n'
+ # Print out individual tiles
+ rows += (' ' % (files[i], files[i])) + ('%s | \n' % files[i])
+ # Finish a row
+ if i % 3 == 2:
+ rows += '
\n'
+
+ variables = super().template_variables()
+ variables["rows"] = rows
+ return variables
+
+ def indexAction(self):
+ self.serve_template("files.html", **self.template_variables())
diff --git a/owrx/http.py b/owrx/http.py
index 347bacff..ebb35b70 100644
--- a/owrx/http.py
+++ b/owrx/http.py
@@ -1,6 +1,7 @@
from owrx.controllers.status import StatusController
from owrx.controllers.template import IndexController, MapController, PolicyController
from owrx.controllers.feature import FeatureController
+from owrx.controllers.file import FilesController, FileController
from owrx.controllers.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController
from owrx.controllers.websocket import WebSocketController
from owrx.controllers.api import ApiController
@@ -96,6 +97,8 @@ class Router(object):
StaticRoute("/map", MapController),
StaticRoute("/policy", PolicyController),
StaticRoute("/features", FeatureController),
+ StaticRoute("/files", FilesController),
+ RegexRoute("^/files/(SSTV-[0-9]+-[0-9]+\.bmp)$", FileController),
StaticRoute("/api/features", ApiController),
StaticRoute("/metrics", MetricsController, options={"action": "prometheusAction"}),
StaticRoute("/metrics.json", MetricsController),