NextJs 13 API 无法使用 formidable 来处理上传文件

问题描述 投票:0回答:3

我有一个 NextJs 13 项目,需要 API 来处理发送给它的文件。我已经使用 formidable 来处理中间件

我的 app/api/uploadfile/route.ts 文件(代码已最小化以便集中)

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 });
  }
}

这里我通过 postman 使用端点 localhost:3000/api/uploadfile 调用 api

我收到错误

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)

我尝试过的事情

  1. 使用 multer 作为替代方案(NextJS 13 和 typescript 的奇怪制品)(尝试了各种实现)
  2. 在代码示例中使用 POST 和 GET 代替 PUT
  3. 谷歌搜索错误并使用chatgpt
  4. 将 formidable 版本更改为 v2/v3 以及 v1.2.2,结果是相同的
  5. 可以上传到我的 prisma db 的更好代码(但调用 api 步骤本身失败)

我的最终目标

我想在我的ckeditor5实现中使用这个API端点(作为图像上传适配器)

node.js typescript next.js ckeditor5 formidable
3个回答
1
投票

看起来我们不需要使用 Nextjs 进行强大的、多方的或多方的操作,因为它可以处理这个问题。如果您遇到类似问题,请尝试此操作。 https://github.com/vercel/next.js/issues/48875#issuecomment-1592301037


0
投票

我通过将 api 移至页面文件夹 (pages/api/uploadfile.ts) 来修复此问题,无需更改任何代码。

我发现这是使其发挥作用的唯一方法。我猜发生的情况是应用程序目录中的 api 无法被邮递员等外部应用程序访问,但我不完全确定。


0
投票

你不再需要强大的力量。 Next.js 13 在其应用程序中添加了一个新功能

formData();
来处理文件上传,并限制了处理此功能的 formidable 的使用。所以就是这样(我正在回答你的目标:使用 CKEditor5 来处理这个问题。也可以使用邮递员):

  const formData = await request.formData();
  const file: any = formData.get("upload");

对我来说,我需要将文件上传到cloudinary,所以这就是我解决它的方法。

 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);
    });

如果您

console.log(result)
,您将看到文件的返回值。返回 secure_url,它将把图像返回到编辑器中。

© www.soinside.com 2019 - 2024. All rights reserved.