Reputation: 492
I am using next js 13 route handler to get a login form data . I think I should be able to get it using formData
method but it returns an empty object.
My login page in app/login/page.jsx:
export default function Page() {
return (
<div>
<form action="/api" method="post" className="...">
<input type="text" name="username" id="username" className="..." />
<input type="password" name="password" id="username" className="..." />
<input type="submit" id="submit" value="submit" className="..." />
</form>
</div>
)
}
and app/api/route.js:
import { NextResponse } from 'next/server';
export async function POST(request):
const data = request.formData();
return NextResposne.json({ data })
and this is my response after submitting the form:
{"data":{}}
Any idea ? thanks
Upvotes: 7
Views: 14955
Reputation: 1
I solved it this way
export async function POST(req) {
try {
const formData = await req.formData();
const file = formData.get('file'); // or what you need
const buffer = Buffer.from(await file.arrayBuffer());
// ready your file on buffer
} catch (error) {
return NextResponse.json({ error: error });
}
}
Upvotes: 0
Reputation: 353
If you are like me and you are using app-router but your API lives in pages/api
then the only way I found that works, is to send the file as base64 string. Decode into a Buffer, create a new form-data and send it. The whole file looks like this:
import { API_ENDPOINTS } from '@/API/api';
import { ironOptions } from '@/config/iron-config';
import { AuthData } from '@/models/AuthData';
import { getIronSession } from 'iron-session';
import { NextApiRequest, NextApiResponse } from 'next';
import fetch from 'node-fetch';
import FormData from 'form-data';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const session = await getIronSession<AuthData>(req, res, ironOptions);
const body = req.body;
//
//Convert Base64 to Buffer
const buffer = Buffer.from(JSON.parse(body).file, 'base64');
// Create a new FormData instance
const formData = new FormData();
formData.append('file', buffer);
//
let url = `${API_ENDPOINTS['upload_media'].url}`;
let method = API_ENDPOINTS['upload_media'].type;
var myHeaders = new Headers();
myHeaders.append('Authorization', `JWT ${session.token}`);
myHeaders.append('Content-Type', formData.getHeaders()['content-type']);
// get user from database then:
const response = await fetch(url, {
method: method,
headers: myHeaders,
body: formData,
});
// if error return the error
const data = await response.json();
if (response.status >= 400) return res.status(response.status).json(data);
return res.status(response.status).json(data);
}
On the client side you can do the following to get the base64:
function getBase64(file: File) {
var fileReader = new FileReader();
if (file) {
fileReader.readAsDataURL(file);
}
return new Promise<string | null>((resolve, reject) => {
fileReader.onload = function (event: any) {
resolve(event?.target?.result);
};
});
}
const reader = new FileReader();
reader.onload = (e: any) => {
setSelectedFile(e.target.result);
};
reader.readAsDataURL(event.target.files[0]);
let result: string | null = await getBase64(event.target.files[0]);
Upvotes: -1
Reputation: 927
Try this:
export const config = {runtime: 'edge'};
export default async function POST(request) {
const formData = await request.formData()
const name = formData.get('name')//get name property
return NextResponse.json({ name })
}
Upvotes: 0
Reputation: 1
you should await it, like this:
const data = await request.formData();
Upvotes: -1
Reputation: 24073
The Nextjs docs were terrible and didn't clarify this.
After lots of trial and error, I finally found that this works:
import { type NextRequest } from 'next/server';
// ...
export async function POST(request: NextRequest) {
const data = await request.json();
console.log({ data });
// ...
}
Note: Use NextRequest
instead of NextApiRequest
.
Upvotes: 1
Reputation: 111
This is working on my side and I am using js not ts.
import { NextResponse } from 'next/server'
export async function POST(request) {
// return NextResponse.json({ data: "working fine" })
const formData = await request.formData()
const name = formData.get('name')
const email = formData.get('email')
const myfile = formData.get('myfile')
console.log(myfile);
return NextResponse.json({ name, email })
}
Upvotes: 4
Reputation: 49571
.formData
returns Promise
(method) Body.formData(): Promise<FormData>
You should await it:
const data = await request.formData();
Upvotes: 0