implement dynamic file upload

This commit is contained in:
Jakob Ketterl 2021-02-08 23:29:24 +01:00
parent 2d72055070
commit a1c024bfe2
7 changed files with 95 additions and 5 deletions

View File

@ -0,0 +1,35 @@
$.fn.imageUpload = function() {
var $button = $(this).find('button');
var $img = $(this).find('img');
var $input = $(this).find('input');
var id = $input.prop('id');
console.info(id);
$button.click(function(){
$button.prop('disabled', true);
var input = document.createElement('input');
input.type = 'file';
input.accept = 'image/jpeg, image/png';
input.onchange = function(e) {
var reader = new FileReader()
reader.readAsArrayBuffer(e.target.files[0]);
reader.onload = function(e) {
$.ajax({
url: '/imageupload?id=' + id,
type: 'POST',
data: e.target.result,
processData: false,
contentType: 'application/octet-stream',
}).done(function(data){
$input.val(data.uuid);
$img.prop('src', "/imageupload?id=" + id + "&uuid=" + data.uuid);
}).always(function(){
$button.prop('disabled', false);
});
}
};
input.click();
return false;
});
}

View File

@ -22,4 +22,5 @@ $(function(){
});
$(".sdrdevice").sdrdevice();
$(".imageupload").imageUpload();
});

View File

@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
class GzipMixin(object):
def send_response(self, content, headers=None, content_type="text/html", *args, **kwargs):
def send_response(self, content, code=200, headers=None, content_type="text/html", *args, **kwargs):
if self.zipable(content_type) and "accept-encoding" in self.request.headers:
accepted = [s.strip().lower() for s in self.request.headers["accept-encoding"].split(",")]
if "gzip" in accepted:
@ -23,7 +23,7 @@ class GzipMixin(object):
if headers is None:
headers = {}
headers["Content-Encoding"] = "gzip"
super().send_response(content, headers=headers, content_type=content_type, *args, **kwargs)
super().send_response(content, code, headers=headers, content_type=content_type, *args, **kwargs)
def zipable(self, content_type):
types = ["application/javascript", "text/css", "text/html"]
@ -78,7 +78,7 @@ class AssetsController(GzipMixin, ModificationAwareController, metaclass=ABCMeta
f.close()
if content_type is None:
(content_type, encoding) = mimetypes.MimeTypes().guess_type(file)
(content_type, encoding) = mimetypes.MimeTypes().guess_type(self.getFilePath(file))
self.send_response(data, content_type=content_type, last_modified=modified, max_age=3600)
except FileNotFoundError:
self.send_response("file not found", code=404)
@ -137,6 +137,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController):
"lib/Header.js",
"lib/settings/Input.js",
"lib/settings/SdrDevice.js",
"lib/settings/ImageUpload.js",
"settings.js",
],
}

View File

@ -0,0 +1,32 @@
from owrx.controllers.assets import AssetsController
from owrx.config import CoreConfig
import uuid
import json
class ImageUploadController(AssetsController):
def __init__(self, handler, request, options):
super().__init__(handler, request, options)
self.uuid = request.query["uuid"][0] if "uuid" in request.query else None
self.id = request.query["id"][0] if "id" in request.query else None
def getFilePath(self, file=None):
if self.uuid is None:
raise FileNotFoundError("missing uuid")
if self.id is None:
raise FileNotFoundError("missing id")
return "{tmp}/{file}-{uuid}".format(
tmp=CoreConfig().get_temporary_directory(),
file=self.id,
uuid=self.uuid,
)
def indexAction(self):
self.serve_file(None)
def processImage(self):
self.uuid = uuid.uuid4().hex
contents = self.get_body()
with open(self.getFilePath(), 'wb') as f:
f.write(contents)
self.send_response(json.dumps({"uuid": self.uuid}), content_type="application/json")

View File

@ -19,6 +19,7 @@ from owrx.form.receiverid import ReceiverKeysConverter
from owrx.form.aprs import AprsBeaconSymbols, AprsAntennaDirections
from owrx.form.wfm import WfmTauValues
from owrx.form.wsjt import Q65ModeMatrix
from owrx.form.gfx import AvatarInput
from urllib.parse import quote
from owrx.wsjt import Fst4Profile, Fst4wProfile
import json
@ -107,6 +108,13 @@ class GeneralSettingsController(AdminController):
TextInput("photo_title", "Photo title"),
TextAreaInput("photo_desc", "Photo description"),
),
Section(
"Receiver images",
AvatarInput(
"receiver_avatar",
"Receiver Avatar",
),
),
Section(
"Receiver listings",
TextAreaInput(

View File

@ -2,6 +2,16 @@ from owrx.form import Input
class AvatarInput(Input):
def render_input(self, value):
pass
def __init__(self, id, label, infotext=None):
super().__init__(id, label, infotext=infotext)
def render_input(self, value):
return """
<div class="imageupload">
<input type="hidden" id="{id}" name="{id}">
<img class="webrx-rx-avatar" src="static/gfx/openwebrx-avatar.png" alt="Receiver avatar"/>
<button class="btn btn-primary">Upload new image...</button>
</div>
""".format(
id=self.id
)

View File

@ -7,6 +7,7 @@ from owrx.controllers.metrics import MetricsController
from owrx.controllers.settings import SettingsController, GeneralSettingsController, SdrSettingsController
from owrx.controllers.session import SessionController
from owrx.controllers.profile import ProfileController
from owrx.controllers.imageupload import ImageUploadController
from http.server import BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import re
@ -112,6 +113,8 @@ class Router(object):
StaticRoute("/logout", SessionController, options={"action": "logoutAction"}),
StaticRoute("/pwchange", ProfileController),
StaticRoute("/pwchange", ProfileController, method="POST", options={"action": "processPwChange"}),
StaticRoute("/imageupload", ImageUploadController),
StaticRoute("/imageupload", ImageUploadController, method="POST", options={"action": "processImage"}),
]
def find_route(self, request):