diff options
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/Buttons.hx | 71 | ||||
| -rw-r--r-- | src/client/FileUploader.hx | 93 | ||||
| -rw-r--r-- | src/client/Utils.hx | 21 |
3 files changed, 117 insertions, 68 deletions
diff --git a/src/client/Buttons.hx b/src/client/Buttons.hx index 78b1c5a..56f28d5 100644 --- a/src/client/Buttons.hx +++ b/src/client/Buttons.hx @@ -1,20 +1,15 @@ package client; -import Types.UploadResponse; import client.Main.getEl; -import haxe.Json; import haxe.Timer; import js.Browser.document; import js.Browser.window; -import js.html.Blob; import js.html.Element; import js.html.ImageElement; import js.html.InputElement; import js.html.KeyboardEvent; -import js.html.ProgressEvent; import js.html.TransitionEvent; import js.html.VisualViewport; -import js.html.XMLHttpRequest; class Buttons { static var split:Split; @@ -263,69 +258,9 @@ class Buttons { } getEl("#mediaurl-upload").onclick = e -> { - Utils.browseFile((buffer, name) -> { - name ??= ""; - name = ~/[?#%\/\\]/g.replace(name, "").trim(); - if (name.length == 0) name = "video"; - name = (window : Dynamic).encodeURIComponent(name); - - // send last chunk separately to allow server file streaming while uploading - final chunkSize = 1024 * 1024 * 5; // 5 MB - final bufferOffset = (buffer.byteLength - chunkSize).limitMin(0); - final lastChunk = buffer.slice(bufferOffset); - final chunkReq = window.fetch("/upload-last-chunk", { - method: "POST", - headers: { - "content-name": name, - }, - body: lastChunk, - }); - chunkReq.then(e -> { - e.json().then((data:UploadResponse) -> { - if (data.errorId != null) { - main.serverMessage(data.info, true, false); - return; - } - final input:InputElement = getEl("#mediaurl"); - input.value = data.url; - }); - }); - - final request = new XMLHttpRequest(); - request.open("POST", "/upload", true); - request.setRequestHeader("content-name", name); - - request.upload.onprogress = (event:ProgressEvent) -> { - var ratio = 0.0; - if (event.lengthComputable) { - ratio = (event.loaded / event.total).clamp(0, 1); - } - main.onProgressEvent({ - type: Progress, - progress: { - type: Uploading, - ratio: ratio - } - }); - } - - request.onload = (e:ProgressEvent) -> { - final data:UploadResponse = try { - Json.parse(request.responseText); - } catch (e) { - trace(e); - return; - } - if (data.errorId == null) return; - main.serverMessage(data.info, true, false); - } - request.onloadend = () -> { - Timer.delay(() -> { - main.hideDynamicChin(); - }, 500); - } - - request.send(new Blob([buffer])); + Utils.browseJsFile(file -> { + final uploader = new FileUploader(main); + uploader.uploadFile(file); }); } diff --git a/src/client/FileUploader.hx b/src/client/FileUploader.hx new file mode 100644 index 0000000..60cc1d2 --- /dev/null +++ b/src/client/FileUploader.hx @@ -0,0 +1,93 @@ +package client; + +import Types.UploadResponse; +import client.Main.getEl; +import haxe.Json; +import haxe.Timer; +import js.Browser.window; +import js.html.File; +import js.html.InputElement; +import js.html.ProgressEvent; +import js.html.XMLHttpRequest; + +class FileUploader { + final main:Main; + + public function new(main:Main) { + this.main = main; + } + + public function uploadFile(file:File):Void { + var name = ~/[?#%\/\\]/g.replace(file.name, "").trim(); + if (name.length == 0) name = "video"; + name = (window : Dynamic).encodeURIComponent(name); + + // send last chunk separately to allow server file streaming while uploading + uploadLastChunk(file, name, data -> { + if (data.errorId != null) { + main.serverMessage(data.info, true, false); + return; + } + final input:InputElement = getEl("#mediaurl"); + input.value = data.url; + + uploadFullFile(name, file); + }); + } + + function uploadFullFile(name:String, file:File):Void { + final request = new XMLHttpRequest(); + request.open("POST", "/upload", true); + request.setRequestHeader("content-name", name); + + request.upload.onprogress = (event:ProgressEvent) -> { + var ratio = 0.0; + if (event.lengthComputable) { + ratio = (event.loaded / event.total).clamp(0, 1); + } + main.onProgressEvent({ + type: Progress, + progress: { + type: Uploading, + ratio: ratio + } + }); + } + + request.onload = (e:ProgressEvent) -> { + final data:UploadResponse = try { + Json.parse(request.responseText); + } catch (e) { + trace(e); + return; + } + if (data.errorId == null) return; + main.serverMessage(data.info, true, false); + } + request.onloadend = () -> { + Timer.delay(() -> { + main.hideDynamicChin(); + }, 500); + } + + request.send(file); + } + + function uploadLastChunk(file:File, name:String, callback:(data:UploadResponse) -> Void):Void { + final chunkSize = 1024 * 1024 * 5; // 5 MB + final bufferOffset = (file.size - chunkSize).limitMin(0); + final lastChunk = file.slice(bufferOffset); + final chunkReq = window.fetch("/upload-last-chunk", { + method: "POST", + headers: { + "content-name": name, + }, + body: lastChunk, + }); + chunkReq.then(e -> { + e.json().then((data:UploadResponse) -> { + callback(data); + }); + }); + } +} diff --git a/src/client/Utils.hx b/src/client/Utils.hx index 2234a1b..54025aa 100644 --- a/src/client/Utils.hx +++ b/src/client/Utils.hx @@ -6,6 +6,7 @@ import js.Browser.navigator; import js.Browser.window; import js.html.Blob; import js.html.Element; +import js.html.File; import js.html.FileReader; import js.html.URL; import js.html.audio.AudioContext; @@ -181,6 +182,26 @@ class Utils { input.click(); } + /** Don't extract data for bigger files. **/ + public static function browseJsFile( + onFileSelected:(file:File) -> Void + ):Void { + final input = document.createInputElement(); + input.style.visibility = "hidden"; + input.type = "file"; + input.id = "browse"; + input.onclick = e -> { + e.cancelBubble = true; + e.stopPropagation(); + } + input.onchange = e -> { + final file = input.files[0] ?? return; + onFileSelected(file); + } + document.body.appendChild(input); + input.click(); + } + public static function saveFile(name:String, mime:Mime, data:String):Void { final blob = new Blob([data], { type: mime |
