Skip to content

Instantly share code, notes, and snippets.

@mateosantosdev
Last active September 22, 2023 19:39
Show Gist options
  • Save mateosantosdev/9a1acb802ddcafb31f16b1cd047e6c5b to your computer and use it in GitHub Desktop.
Save mateosantosdev/9a1acb802ddcafb31f16b1cd047e6c5b to your computer and use it in GitHub Desktop.

Revisions

  1. mateosantosdev revised this gist Sep 22, 2023. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions api.upload-photo.ts
    Original file line number Diff line number Diff line change
    @@ -9,10 +9,10 @@ export async function action({ request }: ActionFunctionArgs) {
    const id = formData.get('id')?.toString();
    if (!id) throw new Error('Id is required');

    const upload = formData.get('photo') as File;
    if (upload.size === 0) throw new Error('File is required');
    const avatar = formData.get('photo') as File;
    if (avatar.size === 0) throw new Error('File is required');

    const uploadedImageName = await uploadAvatar(upload);
    const uploadedImageName = await uploadAvatar(avatar);

    return json({ error: false, ok: true, image: uploadedImageName });
    } catch (error: any) {
  2. mateosantosdev revised this gist Sep 22, 2023. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion api.upload-photo.ts
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,4 @@
    import { json, type ActionFunctionArgs } from '@remix-run/node';
    import { AnimalService } from '~/services/animal';
    import { requireUserId } from '~/utils/session.server';
    import { uploadAvatar } from '~/utils/upload.server';
    import { badRequest } from '~/utils/utils';
  3. mateosantosdev created this gist Sep 22, 2023.
    14 changes: 14 additions & 0 deletions UploadAvatar.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,14 @@
    <fetcher.Form
    method="post"
    encType="multipart/form-data"
    action="/api/upload-photo"
    >
    <input type="hidden" name="id" value="the user id" />
    <input type="file" name="photo" id="photo" accept="image/*" />
    <button
    type="submit"
    disabled={fetcher.state !== 'idle'}
    >
    {fetcher.state === 'idle' ? 'Submit' : 'Loading...'}
    </button>
    </fetcher.Form>
    24 changes: 24 additions & 0 deletions api.upload-photo.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    import { json, type ActionFunctionArgs } from '@remix-run/node';
    import { AnimalService } from '~/services/animal';
    import { requireUserId } from '~/utils/session.server';
    import { uploadAvatar } from '~/utils/upload.server';
    import { badRequest } from '~/utils/utils';
    export async function action({ request }: ActionFunctionArgs) {
    const userId = await requireUserId(request);
    const formData = await request.formData();
    try {
    const id = formData.get('id')?.toString();
    if (!id) throw new Error('Id is required');

    const upload = formData.get('photo') as File;
    if (upload.size === 0) throw new Error('File is required');

    const uploadedImageName = await uploadAvatar(upload);

    return json({ error: false, ok: true, image: uploadedImageName });
    } catch (error: any) {
    return badRequest({
    uploadError: error.message || 'Unknown error'
    });
    }
    }
    30 changes: 30 additions & 0 deletions upload.server.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    import { fileTypeFromBuffer } from 'file-type';
    import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
    import { createId } from '@paralleldrive/cuid2';

    const s3 = new S3Client({
    region: 'eu-west-1',
    credentials: {
    accessKeyId: process.env.S3_AWS_KEY || '',
    secretAccessKey: process.env.S3_AWS_SECRET || ''
    }
    });

    export async function uploadAvatar(file: File) {
    const imageName = `${createId()}.${file.name.split('.').slice(-1)}`;

    const arrayBuffer = await file.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);
    const mime = await fileTypeFromBuffer(buffer);

    const uploadToS3Command = new PutObjectCommand({
    Bucket: process.env.S3_BUCKET_NAME || '',
    Key: imageName,
    Body: buffer,
    ACL: 'public-read',
    ContentType: mime?.mime
    });
    await s3.send(uploadToS3Command);

    return imageName;
    }