[▲ Vercel Community](/) · [Categories](/categories) · [Latest](/latest) · [Top](/top) · [Live](/live) [Help](/c/help/9) # Failed to parse body as FormData 425 views · 0 likes · 2 posts Gokugoru (@gokugoru) · 2024-07-20 Hello, when I push app to Vercel and upload the file I got an error. But if I use localhost url to upload the file - it works well **Server logs:** ``` ⨯ TypeError: Failed to parse body as FormData. at node:internal/deps/undici/undici:4249:27 at successSteps (node:internal/deps/undici/undici:4288:27) at fullyReadBody (node:internal/deps/undici/undici:2724:9) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async consumeBody (node:internal/deps/undici/undici:4297:7) at async v (/var/task/.next/server/app/api/upload/route.js:6:9774) at async /var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:42484 at async eI.execute (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:32486) at async eI.handle (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:43737) at async Y (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:16:24600) ``` **page.tsx:** ``` import { Card } from '@/components/ui/card'; import { handleSubmit } from '@/actions'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; const Page = () => { return ( <Card className='p-3'> <form action={handleSubmit}> <Input type='file' name='files' /> <Button type='submit' className='mt-10'> Submit </Button> </form> </Card> ); }; export default Page; ``` **server action:** ``` 'use server'; export const handleSubmit = async (e: FormData) => { const response = await fetch('https://dvzh.tech/api/upload', { method: 'POST', body: e, headers: { 'X-Upload-Folder': 'test', }, }); const data = await response.json(); console.log('data', data); }; ``` **src/app/api/upload/route.ts:** ``` import { NextRequest, NextResponse } from 'next/server'; import { put } from '@vercel/blob'; import { nanoid } from 'nanoid'; export async function POST(request: NextRequest) { const folder = request.headers.get('X-Upload-Folder') || 'any'; const uniqueName = nanoid(32); const form = await request.formData(); const file = form.get('files') as File; const extension = file.name.split('.').pop(); const fileName = `${uniqueName}.${extension}`; const blob = await put(`${folder}/${fileName}`, file, { access: 'public', }); return NextResponse.json(blob, { status: 201 }); // return await uploadFile(request, folder!); } ``` **also middleware:** ``` import authConfig from '@/auth.config'; import NextAuth from 'next-auth'; import { API_ROUTES, authRoutes, DEFAULT_REDIRECT, publicApiRoutes, publicRoutes, } from '@/routes'; import { NextResponse } from 'next/server'; export const { auth } = NextAuth(authConfig); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error export default auth((req) => { const { nextUrl } = req; const isLoggedIn = !!req.auth; const requestHeaders = new Headers(req.headers); requestHeaders.set('x-url', nextUrl.pathname); requestHeaders.set('x-search', nextUrl.search); const isApiAuthRoute = nextUrl.pathname.startsWith(API_ROUTES.AUTH); const isPublicRoute = publicRoutes.includes(nextUrl.pathname); const isAuthRoute = authRoutes.includes(nextUrl.pathname); const isPublicApiRoute = (publicApiRoutes as string[]).includes( nextUrl.pathname, ); // Allow public API routes if (isPublicApiRoute || isApiAuthRoute) { return null; } // Authentication pages if (isAuthRoute) { // The way to create an absolute url if (isLoggedIn) { return Response.redirect(new URL(DEFAULT_REDIRECT, nextUrl)); } return null; } if (!isLoggedIn && !isPublicRoute) { // Redirect to previous page after login let callbackUrl = nextUrl.pathname; if (nextUrl.search) { callbackUrl += nextUrl.search; } const encodedCallbackUrl = encodeURIComponent(callbackUrl); return Response.redirect( new URL(`/auth/login?callbackUrl=${encodedCallbackUrl}`, nextUrl), ); } return NextResponse.next({ request: { headers: requestHeaders, }, }); }); // Optionally, don't invoke Middleware on some paths export const config = { matcher: [ // Exclude files with a "." followed by an extension, which are typically static files. // Exclude files in the _next directory, which are Next.js internals. '/((?!.+\\.[\\w]+$|_next).*)', // Re-include any files in the api or trpc folders that might have an extension '/(api|trpc)(.*)', ], }; ``` Pauline P. Narvas (@pawlean) · 2024-07-24 Hi @gokugoru! I'm just following up here. It's been a few days, did you manage to figure this out?