From d0ee1296c4c03df86aafc26ff618350ed2f3e7a8 Mon Sep 17 00:00:00 2001 From: April Hall Date: Fri, 21 Feb 2025 18:35:00 -0500 Subject: [PATCH] feat: Framework for profile uploads with Minio --- .gitignore | 3 ++ bun.lockb | Bin 222255 -> 237766 bytes package.json | 2 + src/lib/components/forms/updatePFP.svelte | 20 ++++++-- src/lib/functions/generateReadableStream.ts | 13 +++++ src/lib/server/storage/minio-client.ts | 54 ++++++++++++++++++++ src/routes/(server)/api/upload/+server.ts | 3 ++ 7 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/lib/functions/generateReadableStream.ts create mode 100644 src/lib/server/storage/minio-client.ts create mode 100644 src/routes/(server)/api/upload/+server.ts diff --git a/.gitignore b/.gitignore index 1ad6528..d2ae1c0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ vite.config.ts.timestamp-* # Sqlite src/lib/server/db/users.db* + +# Storage +minio-storage diff --git a/bun.lockb b/bun.lockb index cefd2efbb2d09c92fcb5dde2a66163708441cd20..4f9038efc718eeb8d3345d413698358d0711d80d 100755 GIT binary patch delta 49052 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 delta 40022 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 QO0vv + import { generateStream } from '$lib/functions/generateReadableStream'; import { Button } from '$lib/components/ui/button/index'; - import { Input } from '$lib/components/ui/input/index'; + + let files: FileList; + + function submit() { + if (files.length === 0) return; + generateStream(files[0]); + } -
+
Upload Profile Image - +
diff --git a/src/lib/functions/generateReadableStream.ts b/src/lib/functions/generateReadableStream.ts new file mode 100644 index 0000000..6833587 --- /dev/null +++ b/src/lib/functions/generateReadableStream.ts @@ -0,0 +1,13 @@ +export async function generateStream(file: File): Promise { + try { + await fetch(`/api/upload/`, { + method: 'POST', + body: file, + }); + + return true; + } catch (e) { + console.error(`Error sending stream: ${(e as Error).message}`); + return false; + } +} diff --git a/src/lib/server/storage/minio-client.ts b/src/lib/server/storage/minio-client.ts new file mode 100644 index 0000000..d80c2a7 --- /dev/null +++ b/src/lib/server/storage/minio-client.ts @@ -0,0 +1,54 @@ +import * as Minio from 'minio'; +import { Readable } from 'stream'; +import { v4 } from 'uuid'; + +interface ClientParams { + endPoint: string; + port: number; + accessKey: string; + secretKey: string; + useSSL: boolean; +} + +class MinioClient { + private client: Minio.Client; + + constructor(params: ClientParams) { + this.client = new Minio.Client({ + endPoint: params.endPoint, + port: params.port, + useSSL: params.useSSL, + accessKey: params.accessKey, + secretKey: params.secretKey, + }); + } + + async uploadProfile(stream: Readable) { + try { + const bucket = 'profile-photos'; + if (await !this.client.bucketExists(bucket)) { + await this.client.makeBucket(bucket, 'us-east-1'); + console.log('Bucket "' + bucket + '" created in "us-east-1".'); + } + + const upload = await this.client.putObject(bucket, v4(), stream); + console.log(upload); + } catch (e) { + console.error(`Error uploading file: ${(e as Error).message}`); + } + } +} + +let fsClient: MinioClient | undefined; + +if (process.env.BUILDING !== 'true') { + fsClient = new MinioClient({ + endPoint: 'localhost', + port: 9000, + accessKey: 'minioadmin', + secretKey: 'minioadmin', + useSSL: false, + }); +} + +export { fsClient }; diff --git a/src/routes/(server)/api/upload/+server.ts b/src/routes/(server)/api/upload/+server.ts new file mode 100644 index 0000000..088d2f1 --- /dev/null +++ b/src/routes/(server)/api/upload/+server.ts @@ -0,0 +1,3 @@ +export const POST = async () => { + return new Response(undefined, { status: 204 }); +};