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-errorexport 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