Next.js Discord

Discord Forum

upload image via mongoose to MongoDB from client component form

Answered
Tramp ant posted this in #help-forum
Open in Discord
Tramp antOP
Hi! I'm new to next.js

I'm trying to upload a small image collected via a form directly to my mongodb with mongoose. I have two issues:
- I'm struggling to add "required" to the mongoose schema for the image field.
- My actual image data isn't being stored in the mongodb despite providing the image handle to mongoose.
so I can't retrieve the image later in my program.

I'm not sure whether I need to somehow convert the image to BSON to put in the buffer in my image schema or if the server action never actually receives the image. I'm really stuck, but I'm hoping this is a simple fix. Could someone advise?

models.js
import mongoose from "mongoose";
const mySchema = new mongoose.Schema({
    ...
    img: {
        data: Buffer,
        contentType: String,
        //required: true
    },
    imgMIME: {
        type: String,
        required: true,
    },
    ...
});

export const MySchema = mongoose.models.MySchema || mongoose.model("MySchema", mySchema);


action.js
"use server"
import { MySchema } from "@/lib/models";
import { connectToDb } from "@/lib/utils";

export const addMySchema = async (formData) => {
    await connectToDb();
    ...
    const image = formData.get('image');
    try{
        const myS = new MySchema({
          ...
          img:image,
          imgMIME: image.type,
          ...
});
        await myS.save();
    }
    catch (error){
        console.error("Error saving...", error);
    }
}


uploader.js
"use client"
import { useState } from 'react';
import { addMySchema  } from '@/lib/action';

function Uploader() {
    const [formValues, setFormValues] = useState({
        image: null,
        ...
      });
    const handleFileChange = (e) => {
        const selectedFile = e.target.files[0];
        setFormValues(prevState => ({
          ...prevState,
          image: selectedFile
        }));
      };
     const handleSubmit = async (e) => {
        e.preventDefault();
        const formData = new FormData();
        formData.append('image', image);
        await addMySchema(formData);};
     return (
         <form onSubmit={handleSubmit}>
         <div>
            <label htmlFor="image">Image:</label>
            <input
            type="file"
            id="image"
            name="image"
            accept="image/*"
            onChange={handleFileChange}
            />
         </div>
        <button type="submit">Submit</button>
        </form> 
);}
export default Uploader;
Answered by Tramp ant
uploader.js
const imageData = image instanceof File ? await image.arrayBuffer() : null; // Convert to ArrayBuffer
if (imageData) {
            const blob = new Blob([imageData]); 
            formData.append("imageData", blob); 
        }

action.js
const imageData = await formData.get('imageData').arrayBuffer();
(send to img)

models.js
img: {
        data: {
            type: Buffer,
            required: true
        },
        contentType: {
            type: String,
            required: true
        }
    },

Fixed. ty!
View full answer

1 Reply

Tramp antOP
uploader.js
const imageData = image instanceof File ? await image.arrayBuffer() : null; // Convert to ArrayBuffer
if (imageData) {
            const blob = new Blob([imageData]); 
            formData.append("imageData", blob); 
        }

action.js
const imageData = await formData.get('imageData').arrayBuffer();
(send to img)

models.js
img: {
        data: {
            type: Buffer,
            required: true
        },
        contentType: {
            type: String,
            required: true
        }
    },

Fixed. ty!
Answer