next.js: NextJS 13.4.2 formidable not working.

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: win32
      Arch: x64
      Version: Windows 10 Home Single Language
    Binaries:
      Node: 20.2.0
      npm: N/A
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.4.4-canary.0
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue or a replay of the bug

npx create-next-app@latest

To Reproduce

export async function POST(req) {
    try {
        const form = new formidable.IncomingForm();
    
        form.parse(req, (err, fields, file) => {
            console.log('Successfully worked.........');
        // Do something with the fields but Nextjs 13.4.2 in this fields not worked. Not showing this data in this field.
        });
        
        return new Response(JSON.stringify({success: "Successful"}))

    } catch (err) {
        return new Response(JSON.stringify({error: "Server Side Error !"}), {
            status: 500
        })
    }
}

Describe the Bug

When i handle formData with the formidable npm package but formidable not working properly. I am trying another packege like busboy, multiparty npm packge but all of this are not working. please solve this problem. I’m stuck in this problem 1 week.

Expected Behavior

I want to handle my formData. now I used formidable formData parser, but not working this.

Another suggestion: NextJS API request and response Object will do customize like express JS.

Which browser are you using? (if relevant)

Microsoft Edge Version 112.0.1722.68 (Official build) (64-bit)

How are you deploying your application? (if relevant)

No response

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 10
  • Comments: 23 (1 by maintainers)

Most upvoted comments

Hello guys hope all is well I thought I was the only one facing this issue 😔, I been stuck for a almost a day now, do we have another solution beside base64 and having a page dir. @redmatrice was that the only solution to the error “- error TypeError: req.on is not a function”

Hi, i finally was able to upload a file in the new app router, but i did use “fs” not “formidable”, i guess it’s a “formidable” issue maybe it’s not compatible with the new app router!! but anyway here’s my last version hope it helps.

Now i’m using nextjs 13.4.4 but i think it may work for older versions.

File : /app/api/uploadv2/route.ts

import { extname, join } from "path";
import { stat, mkdir, writeFile } from "fs/promises";
import * as dateFn from "date-fns";
import { NextRequest, NextResponse } from "next/server";

function sanitizeFilename(filename: string): string {
  return filename.replace(/[^a-zA-Z0-9_\u0600-\u06FF.]/g, "_");
}


export async function POST(request: NextRequest, res: any) {

  const formData = await request.formData();

  const file = formData.get("file") as Blob | null;
  if (!file) {
    return NextResponse.json(
      { error: "File blob is required." },
      { status: 400 }
    );
  }

  const buffer = Buffer.from(await file.arrayBuffer());

  const pathDist: string = join(process.cwd(), "/public/images");
  const relativeUploadDir = `${dateFn.format(Date.now(), "dd-MM-Y")}`;
  const uploadDir = join(pathDist, relativeUploadDir);


  try {
    await stat(uploadDir);
  } catch (e: any) {
    if (e.code === "ENOENT") {
      await mkdir(uploadDir, { recursive: true });
    } else {
      console.error(
        "Error while trying to create directory when uploading a file\n",
        e
      );
      return NextResponse.json(
        { error: "Something went wrong." },
        { status: 500 }
      );

    }
  }

  try {
    const uniqueSuffix = `${Date.now()}_${Math.round(Math.random() * 1e9)}`;
    const fileExtension = extname(file.name);
    const originalFilename = file.name.replace(/\.[^/.]+$/, "");
    const sanitizedFilename = sanitizeFilename(originalFilename);
    const filename = `${sanitizedFilename}_${uniqueSuffix}${fileExtension}`;
    console.log('filename : ' + filename);
    await writeFile(`${uploadDir}/${filename}`, buffer);

    const finalFilePath = 'http://localhost:3000/images/' + `${relativeUploadDir}/${filename}`;
    return NextResponse.json({ done: "ok", filename: filename, httpfilepath: finalFilePath }, { status: 200 });

  } catch (e) {
    console.error("Error while trying to upload a file\n", e);
    return NextResponse.json(
      { error: "Something went wrong." },
      { status: 500 }
    );
  }
}

i was having the same issue because i’m using /app/api/upimage/route.ts, for almost a week and searched everywhere, but no solution worked, but when i tried the old method in /pages/api/uploadfile.ts it worked straight away, don’t know if it’s a bug or we are doing it wrong but i’m going to the share both version and hope it helps

I’m using : “formidable”: “3.2.5” “next”: “13.4.3”

File : /app/uploader/page.tsx

  const formData = new FormData();
      formData.append("file", selectedFile);
      // "/api/upimage" will give me the error!
      const response = await fetch("/api/uploadfile", {
        method: "POST",
        body: formData ,
      }); 

this code is working and it’s in

File : /pages/api/uploadfile.ts

import { NextApiHandler, NextApiRequest } from "next";
import formidable from "formidable";
import path from "path";
import fs from "fs/promises";

export const config = {
  api: {
    bodyParser: false,
  },
};

const pathDist: string =  path.join(process.cwd(), "/public/images");

const readFile = (
  req: NextApiRequest,
  saveLocally?: boolean
): Promise<{ fields: formidable.Fields; files: formidable.Files }> => {
  const options: formidable.Options = {};
  if (saveLocally) {
    options.uploadDir = pathDist;
    options.filename = (name, ext, path, form) => {
      return Date.now().toString() + "_" + path.originalFilename;
    };
  }
  options.maxFileSize = 4000 * 1024 * 1024;
  options.keepExtensions = true;

  const form = formidable(options);
  return new Promise((resolve, reject) => {
    form.parse(req, (err, fields, files) => {
      if (err) reject(err);
      resolve({ fields, files });
    });
  });
};

const handler: NextApiHandler = async (req: NextApiRequest, res) => {
  try {
    await fs.readdir(pathDist);
  } catch (error) {
    await fs.mkdir(pathDist);
  }

  try{

    const { fields, files } = await readFile(req, true);

    const firstFile = (files as any).file[0];
    const size = firstFile.size;
    const filepath = firstFile.filepath;
    const newFilename = firstFile.newFilename;
    const mimetype = firstFile.mimetype;
    const mtime = firstFile.mtime;
    const originalFilename = firstFile.originalFilename;
    
    console.log(size);
    console.log(filepath);
    console.log(newFilename);
    console.log(mimetype);
    console.log(mtime);
    console.log(originalFilename);
    const finalFilePath = 'http://localhost:3000/images/' + newFilename;

  return await res.status(200).json({ done: "ok" , filename: newFilename, httpfilepath: finalFilePath});
}
catch(error){

  return await res.status(500).json({ done: "not" , filename: '', httpfilepath: ''});
  }
};

export default handler;

But this code gives me the error ‘TypeError: req.on is not a function’

File : /app/api/upimage/route.ts

import { NextApiRequest, NextApiResponse } from "next";
import formidable from "formidable";
import path from "path";
import fs from "fs/promises";
import { NextRequest, NextResponse } from "next/server";

export const config = {
  api: {
    bodyParser: false,
  },
};

const pathDist: string =  path.join(process.cwd(), "/public/images");

const readFile = (
  req: any,
  saveLocally?: boolean
): Promise<{ fields: formidable.Fields; files: formidable.Files }> => {

  
  return new Promise((resolve, reject) => {

    const options: formidable.Options = {};

    if (saveLocally) {
      options.uploadDir = pathDist;
      options.filename = (name, ext, path, form) => {
        const tmp = Date.now().toString() + "_" + path.originalFilename;
        return tmp;
      };
    }
    options.maxFileSize = 1024 * 1024 * 10; // 10mb
    const form = formidable(options);
    
    // the error comes from this line the 'req' variable here
    form.parse(req, (err, fields, files) => {
      if (err) reject(err);
      resolve({ fields, files });
    });
  });
};

export async function POST(req: NextApiRequest) {
 
  try {
    await fs.readdir(pathDist);
  } catch (error) {
    await fs.mkdir(pathDist);
  }

  try{
    const { fields, files } = await readFile(req, true);

    const firstFile = (files as any).file[0];
    const size = firstFile.size;
    const filepath = firstFile.filepath;
    const newFilename = firstFile.newFilename;
    const mimetype = firstFile.mimetype;
    const mtime = firstFile.mtime;
    const originalFilename = firstFile.originalFilename;
    
    console.log(size);
    console.log(filepath);
    console.log(newFilename);
    console.log(mimetype);
    console.log(mtime);
    console.log(originalFilename);

    const finalFilePath = 'http://localhost:3000/images/' + newFilename;

  return await NextResponse.json({ done: "ok" , filename: newFilename, httpfilepath: finalFilePath});
  }
  catch(error){
   console.log(error);
  return await NextResponse.json({ done: "not" , filename: '', httpfilepath: ''});
  }
}

Same problem

Awesome, glad you were able to get this resolved, your solution looks amazing and a great approach. 🎊 🎉

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: win32
      Arch: x64
      Version: Windows 10 Home Single Language
    Binaries:
      Node: 20.2.0
      npm: N/A
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.4.4-canary.0
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue or a replay of the bug

npx create-next-app@latest

To Reproduce

export async function POST(req) {
    try {
        const form = new formidable.IncomingForm();
    
        form.parse(req, (err, fields, file) => {
            console.log('Successfully worked.........');
        // Do something with the fields but Nextjs 13.4.2 in this fields not worked. Not showing this data in this field.
        });
        
        return new Response(JSON.stringify({success: "Successful"}))

    } catch (err) {
        return new Response(JSON.stringify({error: "Server Side Error !"}), {
            status: 500
        })
    }
}

Describe the Bug

When i handle formData with the formidable npm package but formidable not working properly. I am trying another packege like busboy, multiparty npm packge but all of this are not working. please solve this problem. I’m stuck in this problem 1 week.

Expected Behavior

I want to handle my formData. now I used formidable formData parser, but not working this.

Another suggestion: NextJS API request and response Object will do customize like express JS.

Which browser are you using? (if relevant)

Microsoft Edge Version 112.0.1722.68 (Official build) (64-bit)

How are you deploying your application? (if relevant)

No response

I solved it for you، but I didn’t use forimdible scripts، but I first downloaded the file to base64، then created an image using the node-base64-image library، which works.

import { Buffer } from 'buffer';
import { decode } from 'node-base64-image';


function makeid(length = 10) {
    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}

export async function POST(req) {
    try {
        const formData = await req.formData();
        const file = formData.get("file");
        let namefile = makeid(10)
        // Read the file data as a Buffer
        const fileData = await file.arrayBuffer();
        const buffer = Buffer.from(fileData);
        // Convert the buffer to Base64
        const base64Data = buffer.toString('base64');
        await decode(base64Data, { fname: "./public/upload/" + namefile, ext: "png" });
        return new Response(JSON.stringify({success: "Successful"}))
    } catch (err) {
        console.log(err);
        return new Response(JSON.stringify({ error: "Server Side Error !" }), {
            status: 500
        })
    }
}

Can we conclude formidable is a no-no for the new next >13?