New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not able to validate file uploads on the backend, even though it works on the frontend #497
Comments
Is |
|
If you log |
I finally managed to solve this. Leaving my code here in case someone has a hard time figuring this out as well. Client form:"use client";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { useForm } from "react-hook-form";
import { changeAvatar } from "@/lib/actions";
import { changeAvatarSchema, type changeAvatarInput } from "@/lib/validations";
export default function ChangeAvatarForm() {
const { register, handleSubmit, setValue, formState: { errors, isSubmitting } } = useForm<changeAvatarInput>({
resolver: valibotResolver(changeAvatarSchema),
defaultValues: {
avatar: undefined,
},
});
const onAvatarChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files && event.target.files.length > 0 ? event.target.files[0] : undefined;
if (file) {
setValue("avatar", file);
}
};
async function onSubmit(values: changeAvatarInput) {
const formData = new FormData();
formData.append("avatar", values.avatar);
const response = await changeAvatar(formData);
return console.log(response);
}
return (
<form className="space-y-6" onSubmit={handleSubmit(onSubmit)}>
<div className="space-y-2">
<label htmlFor="avatar" className="block text-sm font-medium text-secondary-300">
Avatar
</label>
<input
className="file:mr-2 file:inline-flex file:h-8 file:rounded-lg file:border-0 file:bg-secondary-900 file:px-2.5 file:text-xs file:text-secondary-400"
id="avatar"
name="avatar"
type="file"
onChange={onAvatarChange}
/>
{errors.avatar && <p className="text-xs text-red-500">{errors.avatar.message}</p>}
</div>
<button
className="inline-flex h-10 w-full items-center justify-center rounded-lg bg-brand-500 px-3.5 text-sm font-medium text-white hover:bg-brand-600"
type="submit"
>
Change avatar
</button>
</form>
);
} Server action:"use server";
import { safeParse } from "valibot";
import { changeAvatarSchema } from "@/lib/validations";
type ServerActionResult = {
success: boolean;
error?: string;
};
export async function changeAvatar(values: FormData): Promise<ServerActionResult> {
const avatar = values.get("avatar");
const result = safeParse(changeAvatarSchema, { avatar }, { abortEarly: true });
if (result.success) {
return { success: true };
} else {
return { success: false, error: result.issues[0].message };
}
} Validation:import { Input, instance, maxSize, mimeType, minLength, object, string } from "valibot";
export const changeAvatarSchema = object({
avatar: instance(File, "Avatar is required", [
mimeType(["image/jpeg", "image/png"], "Avatar must be either a JPG or PNG image"),
maxSize(1024 * 1024 * 1, "Avatar size may not exceed 1 MB"),
]),
});
export type changeAvatarInput = Input<typeof changeAvatarSchema>; |
I've been pulling my hair out to get this to work, but I feel like I've hit a wall with this issue I'm not able to solve by myself.
I'm using Nextjs with react-hook-form, valibot and server actions.
Installed dependencies:
Issue
I'm trying to implement a basic image file upload, got the frontend validation working but it seems to break on the backend (server action) using the same validation.
When logging the file to be uploaded on the frontend, it correctly logs the avatar file.
Logging
avatar
inside the server action logs also the exact same file, which looks like this:However, when performing the validation inside the server action like this:
I receive the following error from valibot:
The file for whatever reason is undefined even though I just logged it right above without issues.
Full code
My form on the frontend:
Server action:
Validation:
The text was updated successfully, but these errors were encountered: