feat: Framework for profile uploads with Minio
This commit is contained in:
parent
6adf4afcd7
commit
d0ee1296c4
3
.gitignore
vendored
3
.gitignore
vendored
@ -29,3 +29,6 @@ vite.config.ts.timestamp-*
|
||||
|
||||
# Sqlite
|
||||
src/lib/server/db/users.db*
|
||||
|
||||
# Storage
|
||||
minio-storage
|
||||
|
@ -49,12 +49,14 @@
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@types/better-sqlite3": "^7.6.12",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/minio": "^7.1.1",
|
||||
"better-auth": "^1.1.16",
|
||||
"better-sqlite3": "^11.8.1",
|
||||
"cassandra-driver": "^4.7.2",
|
||||
"express": "^4.21.2",
|
||||
"lucide-svelte": "^0.474.0",
|
||||
"markdown-it-highlightjs": "^4.2.0",
|
||||
"minio": "^8.0.4",
|
||||
"mode-watcher": "^0.5.1",
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-client": "^4.8.1",
|
||||
|
@ -1,12 +1,26 @@
|
||||
<script lang="ts">
|
||||
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]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<form class="grid w-full items-start gap-3">
|
||||
<form class="grid w-full items-start gap-3" onsubmit={submit}>
|
||||
<fieldset class="grid w-full gap-3 rounded-lg border p-4">
|
||||
<legend class="-ml-1 px-1 text-sm font-medium"> Upload Profile Image </legend>
|
||||
<Input type="file" accept="image/jpeg, image/png" />
|
||||
<input
|
||||
class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0
|
||||
file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1
|
||||
focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
|
||||
type="file"
|
||||
accept="image/jpeg, image/png"
|
||||
bind:files
|
||||
/>
|
||||
<Button type="submit">Update Profile Photo</Button>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
13
src/lib/functions/generateReadableStream.ts
Normal file
13
src/lib/functions/generateReadableStream.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export async function generateStream(file: File): Promise<boolean> {
|
||||
try {
|
||||
await fetch(`/api/upload/`, {
|
||||
method: 'POST',
|
||||
body: file,
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(`Error sending stream: ${(e as Error).message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
54
src/lib/server/storage/minio-client.ts
Normal file
54
src/lib/server/storage/minio-client.ts
Normal file
@ -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 };
|
3
src/routes/(server)/api/upload/+server.ts
Normal file
3
src/routes/(server)/api/upload/+server.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const POST = async () => {
|
||||
return new Response(undefined, { status: 204 });
|
||||
};
|
Loading…
Reference in New Issue
Block a user