I have a NextJs 13 project that requires and API which can handle a file that is sent to it. I have used formidable for handling the middleware
My app/api/uploadfile/route.ts file (code has been minimized for concentration)
import { IncomingForm } from "formidable";
export const config = {
api: {
bodyParser: false
}
};
const asyncParse = (req:any) =>
new Promise((resolve, reject) => {
const form = new IncomingForm({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) return reject(err);
resolve({ fields, files });
});
});
export async function PUT(req:any, res:any) {
console.log("Receiving");
if (req.method === "PUT") {
const result = await asyncParse(req);
res.status(200).json({ result });
}
}
Here i call the api using the endpoint localhost:3000/api/uploadfile via postman
I get an error
error - TypeError: req.on is not a function
at IncomingForm.parse (webpack-internal:///(sc_server)/./node_modules/formidable/lib/incoming_form.js:90:9)
at eval (webpack-internal:///(sc_server)/./app/api/uploadfile/route.ts:18:14)
at new Promise (<anonymous>)
at asyncParse (webpack-internal:///(sc_server)/./app/api/uploadfile/route.ts:14:27)
at PUT (webpack-internal:///(sc_server)/./app/api/uploadfile/route.ts:29:30)
at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:219:24)
at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/lib/trace/tracer.js:92:36)
at NoopContextManager.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:360:30)
at ContextAPI.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:30:58)
at NoopTracer.startActiveSpan (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:953:34)
at ProxyTracer.startActiveSpan (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:993:36)
at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/lib/trace/tracer.js:81:107)
at NoopContextManager.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:360:30)
at ContextAPI.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:30:58)
at NextTracerImpl.trace (webpack-internal:///(sc_server)/./node_modules/next/dist/server/lib/trace/tracer.js:81:32)
at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:214:49)
at AsyncLocalStorage.run (node:async_hooks:345:14)
at Object.wrap (webpack-internal:///(sc_server)/./node_modules/next/dist/server/async-storage/static-generation-async-storage-wrapper.js:32:24)
at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:171:93)
at AsyncLocalStorage.run (node:async_hooks:345:14)
at Object.wrap (webpack-internal:///(sc_server)/./node_modules/next/dist/server/async-storage/request-async-storage-wrapper.js:59:24)
at AppRouteRouteModule.execute (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:170:87)
at AppRouteRouteModule.handle (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:259:41)
at RouteHandlerManager.handle (E:\Projects\Templates\backend-template\node_modules\next\dist\server\future\route-handler-managers\route-handler-manager.js:22:29)
at doRender (E:\Projects\Templates\backend-template\node_modules\next\dist\server\base-server.js:848:58)
at cacheEntry1.responseCache.get.incrementalCache.incrementalCache (E:\Projects\Templates\backend-template\node_modules\next\dist\server\base-server.js:1059:34)
at E:\Projects\Templates\backend-template\node_modules\next\dist\server\response-cache\index.js:83:42
at ResponseCache.get (E:\Projects\Templates\backend-template\node_modules\next\dist\server\response-cache\index.js:131:11)
at DevServer.renderToResponseWithComponentsImpl (E:\Projects\Templates\backend-template\node_modules\next\dist\server\base-server.js:978:54)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Things i have tried
My end goal
I want to use this API endpoint in my ckeditor5 implementation(as the image upload adapter)
You don't need formidable anymore for it. Next.js 13 added a new feature formData();
to their application that handles file upload and they restricted the use of formidable which handles this functionality. So this is it (I'm answering your goal: using CKEditor5 to handle this. Might work using postman as well):
const formData = await request.formData();
const file: any = formData.get("upload");
for me I needed the file to be uploaded on cloudinary so this is how I solved it.
const formData = await request.formData();
const file: any = formData.get("upload");
const arrayBuffer = await file.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
let uploadedImageUrl: any = await new Promise((resolve, reject) => {
cloudinary.uploader
.upload_stream({}, function (error, result: any) {
if (error) {
reject(error);
return;
}
resolve(result);
})
.end(buffer);
});
If you console.log(result)
you will see the returned value of your file. return the secure_url and it will return the image into the editor.