Reputation: 29
Im making a form with Next 14 using server actions and integrating some WYSIWYG text editor (ReactQuill). Im getting the form values in the server side but I dont know how to get the buffer value of the images to handle them. Here is the code.
Simplified form:
"use client"
export default function NewCompositionForm() {
const [content, setContent] = useState("");
const createCompositionAction = actions.createComposition.bind(null, content);
return (
<form
className="bg-bgCustom pt-4 h-screen rounded-md px-2"
action={createCompositionAction}
>
...
<div className="flex">
<label htmlFor="edition" className="w-1/6 text-xl">
Imágenes
</label>
<input
type="file"
id="images"
name="images"
className="w-5/6 rounded-md px-2 py-1 text-xl"
placeholder="Introduce Editor"
multiple
/>
</div>
<div className="flex flex-col">
<label htmlFor="ext_media" className="text-xl mb-4">
Descripción y/o anotaciones
</label>
<ReactQuill
value={content}
onChange={setContent}
theme="snow"
id="description"
name="description"
className=" bg-slate-50"
modules={quillModules}
formats={quillFormats}
placeholder="Escribe aquí toda la información de la obra."
/>
</div>
<button type="submit">Agregar</button>
</form>
This the server side:
"use server"
export async function createComposition(content, formData) {
console.log("Content: ", content)
console.log("FormData: ", formData)
console.log(formData.getAll('images'))
}
This is the terminal output:
Content: <p><a href="DUDE" rel="noopener noreferrer" target="_blank"><strong>DUDE</strong></a></p>
FormData: FormData {
[Symbol(state)]: [
{ name: 'type', value: 'camara' },
{ name: 'title', value: 'TITULO!!!' },
{ name: 'rev', value: '' },
{ name: 'length', value: '' },
{ name: 'edition', value: '' },
{ name: 'images', value: [File] },
{ name: 'images', value: [File] }
]
}
File {
size: 13397612,
type: 'image/png',
name: 'Porsche 911 Blue Render.png',
lastModified: 1706694592197
}
``
So how do I handle this multiple files from here?
Thanks
Upvotes: 0
Views: 740
Reputation: 29
Here is the solution for the server action
"use server";
import fs from "fs";
import path from "path";
import util from 'util'
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import { db } from "@/lib/db";
//-------- Definitions -------
const writeFileAsync = util.promisify(fs.writeFile)
export async function createComposition(content, formData) {
console.log("Content: ", content);
console.log("FormData: ", formData);
const title = formData.get("title");
//-------- Image file server handler --------
const files = formData.getAll("images");
const filePath = path.join("public", "/compositions", title);
if (!fs.existsSync(path.resolve(filePath))) {
fs.mkdirSync(path.resolve(filePath), { recursive: true });
console.log("Directory created");
}
const writePromises = files.map(async (file) => {
if (file.type === "image/jpeg") {
const bytes = await file.arrayBuffer();
const buffer = Buffer.from(bytes);
await writeFileAsync(`${path.resolve(filePath)}/${file.name}`, buffer);
}
});
await Promise.all(writePromises)
}
Upvotes: 0