aboutsummaryrefslogtreecommitdiffstats
path: root/src/client/FileUploader.hx
blob: 60cc1d2c7c58bc320048fc7a8d2016f79b48afa5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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);
			});
		});
	}
}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage