aboutsummaryrefslogtreecommitdiffstats
path: root/lib/upload.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/upload.ts')
-rw-r--r--lib/upload.ts70
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/upload.ts b/lib/upload.ts
new file mode 100644
index 00000000..0fb31ea5
--- /dev/null
+++ b/lib/upload.ts
@@ -0,0 +1,70 @@
+import { fileTypeFromStream } from "file-type";
+import pump from "pump";
+import Clone from "readable-stream-clone";
+import fs from "fs";
+import path from "path";
+import { pipeline } from "stream";
+import { g, s, db } from "$lib/db";
+import { bail, fail } from "$lib/utils";
+import crypto from "crypto";
+import { err } from "$lib/logging";
+
+async function getSha256Hash(stream) {
+ return new Promise((resolve, reject) => {
+ const hash = crypto.createHash("sha256");
+ stream.pipe(hash);
+
+ let hashValue;
+ hash.on("data", (data) => {
+ hashValue = data.toString("hex");
+ });
+
+ hash.on("end", () => {
+ resolve(hashValue);
+ });
+
+ hash.on("error", reject);
+ });
+}
+
+export default async (req, res) => {
+ try {
+ let {
+ params: { type },
+ } = req;
+
+ let width = type === "banner" ? 1920 : 240;
+
+ let data = await req.file();
+ let s1 = new Clone(data.file);
+ let s2 = new Clone(data.file);
+
+ let [format, ext] = (await fileTypeFromStream(s1)).mime.split("/");
+
+ if (format !== "image" && !["jpg", "jpeg", "png"].includes(ext))
+ fail("unsupported file type");
+
+ let processedBuffer = await streamToBuffer(s2.pipe(t));
+ let hash = crypto
+ .createHash("sha256")
+ .update(processedBuffer)
+ .digest("hex");
+
+ let filePath = `/home/bun/app/data/uploads/${hash}.webp`;
+ fs.writeFileSync(filePath, processedBuffer);
+
+ res.send({ hash });
+ } catch (e) {
+ err("problem uploading", e.message);
+ bail(res, e.message);
+ }
+};
+
+function streamToBuffer(stream) {
+ return new Promise((resolve, reject) => {
+ const chunks = [];
+ stream.on("data", (chunk) => chunks.push(chunk));
+ stream.on("end", () => resolve(Buffer.concat(chunks)));
+ stream.on("error", reject);
+ });
+}