aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2019-04-07 17:17:17 +0200
committerMarvin Borner2019-04-07 17:17:17 +0200
commit5ec7ec5c50eeb3e2c281c0edfee6c74d7d512500 (patch)
tree071270805b5b2169d4aa26462647f9a5737b231e
parent4e2024432ee680f98d91d07b050ac60151ebec4c (diff)
Added drag and drop file upload
-rw-r--r--src/main/kotlin/App.kt22
-rw-r--r--src/main/resources/css/files.css6
-rw-r--r--src/main/resources/css/layout.css4
-rw-r--r--src/main/resources/js/files.js31
-rw-r--r--src/main/resources/views/files.rocker.html19
-rw-r--r--src/main/resources/views/upload.rocker.html4
6 files changed, 69 insertions, 17 deletions
diff --git a/src/main/kotlin/App.kt b/src/main/kotlin/App.kt
index d79e25e..f69a960 100644
--- a/src/main/kotlin/App.kt
+++ b/src/main/kotlin/App.kt
@@ -49,7 +49,7 @@ fun main() {
* Receives and saves multipart media data
* TODO: Fix possible security issue with "../"
*/
- post("/upload", { ctx -> upload(ctx) }, roles(Roles.ADMIN))
+ post("/upload/*", { ctx -> upload(ctx) }, roles(Roles.ADMIN))
}
}
@@ -66,18 +66,23 @@ fun setupRoles(handler: Handler, ctx: Context, permittedRoles: Set<Role>) {
}
/**
- * Crawls the requested directory and returns filenames in array
+ * Crawls the requested file and either renders the directory view or the file view
*/
fun crawlFiles(ctx: Context) {
- val files = ArrayList<String>()
try {
if (File("$fileHome/${ctx.splats()[0]}").isDirectory) {
+ val files = ArrayList<String>()
Files.list(Paths.get("$fileHome/${ctx.splats()[0]}/")).forEach {
val fileName = it.toString()
.drop(fileHome.length + (if (ctx.splats()[0].isNotEmpty()) ctx.splats()[0].length + 2 else 1))
val filePath = "$fileHome${it.toString().drop(fileHome.length)}"
files.add(if (File(filePath).isDirectory) "$fileName/" else fileName)
- ctx.render("files.rocker.html", model("files", files))
+ ctx.render(
+ "files.rocker.html", model(
+ "files", files,
+ "path", ctx.splats()[0]
+ )
+ )
}
} else
ctx.render(
@@ -99,12 +104,9 @@ fun crawlFiles(ctx: Context) {
* Saves multipart media data into requested directory
*/
fun upload(ctx: Context) {
- ctx.uploadedFiles("files").forEach { (contentType, content, name, extension) ->
- if (ctx.queryParam("dir") !== null) {
- FileUtil.streamToFile(content, "files/${ctx.queryParam("dir")}/$name")
- ctx.redirect("/views/upload.rocker.html")
- } else
- throw BadRequestResponse("Error: Please enter a filename.")
+ ctx.uploadedFiles("file").forEach { (contentType, content, name, extension) ->
+ FileUtil.streamToFile(content, "$fileHome/${ctx.splats()[0]}/$name")
+ ctx.redirect("/upload")
}
}
diff --git a/src/main/resources/css/files.css b/src/main/resources/css/files.css
index 0f55ca6..798e3ec 100644
--- a/src/main/resources/css/files.css
+++ b/src/main/resources/css/files.css
@@ -3,3 +3,9 @@ a.filename {
text-decoration: none;
margin-bottom: 5px;;
}
+
+.drop {
+ padding: 8px;
+ min-height: calc(100vh - 16px);
+ z-index: -1;
+}
diff --git a/src/main/resources/css/layout.css b/src/main/resources/css/layout.css
index 4a1e1f0..c11ee79 100644
--- a/src/main/resources/css/layout.css
+++ b/src/main/resources/css/layout.css
@@ -1,3 +1,7 @@
html, body {
font-family: Arial, Helvetica, sans-serif;
+ padding: 0;
+ margin: 0;
+ min-width: 100%;
+ min-height: 100%;
}
diff --git a/src/main/resources/js/files.js b/src/main/resources/js/files.js
new file mode 100644
index 0000000..24140b0
--- /dev/null
+++ b/src/main/resources/js/files.js
@@ -0,0 +1,31 @@
+const drop = document.getElementById("drop");
+
+drop.addEventListener('dragover', e => {
+ e.stopPropagation();
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ drop.style.background = "rgba(12,99,250,0.3)";
+});
+
+drop.addEventListener('dragleave', e =>
+ drop.style.background = "white"
+);
+
+drop.addEventListener('drop', e => {
+ // TODO: Fix directory uploading
+ e.stopPropagation();
+ e.preventDefault();
+ drop.style.background = "white";
+ const files = e.dataTransfer.files;
+
+ for (let i = 0; i < files.length; i++) {
+ let request = new XMLHttpRequest();
+ let formData = new FormData();
+
+ drop.insertAdjacentHTML('beforeend', `<a class="filename" href="${files[i].name}">${files[i].name}</a><br><hr>`);
+
+ formData.append("file", files[i]);
+ request.open("POST", "/upload/" + path);
+ request.send(formData);
+ }
+});
diff --git a/src/main/resources/views/files.rocker.html b/src/main/resources/views/files.rocker.html
index 7a2d432..1373eca 100644
--- a/src/main/resources/views/files.rocker.html
+++ b/src/main/resources/views/files.rocker.html
@@ -1,13 +1,22 @@
@import java.util.ArrayList
-@args (ArrayList files)
+@args (ArrayList files, String path)
@css => {
<link href="/css/files.css" rel="stylesheet">
}
-@layout.template(files.size() + " Files", css, RockerContent.NONE) -> {
-@for (String file : files) {
-<a class="filename" href="@file">@file</a><br>
-<hr>
+@js => {
+<script>const path = "@path";</script>
+<script src="/js/files.js"></script>
}
+
+@layout.template(files.size() + " Files", css, js) -> {
+<div class="drop" id="drop">
+ <a class="filename" href="../">../</a><br>
+ <hr>
+ @for (String file : files) {
+ <a class="filename" href="@file">@file</a><br>
+ <hr>
+ }
+</div>
}
diff --git a/src/main/resources/views/upload.rocker.html b/src/main/resources/views/upload.rocker.html
index b36abdc..ec5daa2 100644
--- a/src/main/resources/views/upload.rocker.html
+++ b/src/main/resources/views/upload.rocker.html
@@ -1,8 +1,8 @@
@args (String content)
@layout.template("Upload", RockerContent.NONE, RockerContent.NONE) -> {
-<form action="/api/upload?dir=test" enctype="multipart/form-data" method="post">
- <input multiple name="files" type="file">
+<form action="/upload/test" enctype="multipart/form-data" method="post">
+ <input multiple name="file" type="file">
<button>Submit</button>
</form>
}