处理 Koa-BODY 错误:’fields’和‘files’属性为空

处理 Koa-BODY 错误:’fields’和‘files’属性为空

Koa 是一个优雅的 Node.js 框架,由于其简单、灵活和易于扩展,它越来越受到前端开发者的喜爱。然而,当使用 Koa 中间件 Koa-BODY 处理文件上传时,有时可能会遇到 fields 和 files 属性为空的错误。这篇文章将深入探讨此错误的原因,并提供有效的解决方案。

错误描述

当使用 Koa 接收一个包含文本和文件的 multipart/form-data POST 请求时,如果请求不包含任何文件,则使用 Koa-BODY 中间件处理请求后,fields 和 files 属性会变成空。例如:

----- --- - ---------------
----- ------- - --------------------
----- --- - --- ------

-----------------
  ---------- -----
----

------------- ----- -- -
  ------------------------------ 
  -- -- - ------- --- ------ -- -
---

-----------------

如上所示,当请求不包含任何文件时,输出结果会变成:

- ------- --- ------ -- -

原因分析

需要了解以下知识点:

  • 浏览器生成的 multipart/form-data 中包含的 boundary 用于分隔不同数据段;
  • Koa-BODY 中间件默认的 { multipart: true } 选项启用了文件上传检测;
  • Koa-BODY 的文件上传处理是根据表单数据按照 boundary 分割成多段来进行处理的。

当要上传文件时,浏览器会生成一个名为 multipart/form-data 的数据协议,并用一个 boundary 分隔符分隔多个表单项。服务器端的代码会按照这个 boundary 分隔符来解析数据流。当数据中没有文件时,该分割符只被用作一个字符串,因此 Koa-BODY 中间件无法判断是否有文件被上传,所以 fields 和 files 属性为空。

解决方案

方案一:手动处理请求

我们可以不用 Koa-BODY 中间件,而是手动处理请求,在请求中使用 stream 或 pipe 将文件数据写入磁盘,使用 Buffer 类型存储文本数据。以下是示例代码:

----- --- - ---------------
----- ------ - ------------------
----- --- - --- ------

------------- ----- -- -
  -- --------------------------------------- -
    ----- ----- - ---
    ----- ------ - ---
    ----- ------ - --- ---------------- ------------------

    ------------------ ------------------- ---- ------------------- ------------- --------- --------- -
      ----------------- - ----
    ---

    ----------------- ------------------- ----- --------- --------- --------- -
      ----- ------- - ---
      --------------- -------------- -
        -------------------
      ---

      -------------- ---------- -
        ---------------- - -
          ----- -----------------------
          ----- ---------
          --------- ---------
          --------- ---------
        --
      ---
    ---

    ------------------- ---------- -
      ---------------- - - ------ ------ ------- ------ --
    ---

    ------ ---------------------
  -

  ---------------
---

-----------------

在这个示例代码中,我们使用 Busboy 库手动处理请求。这个库支持流式传输,并处理了边界分隔符。在处理文件时,我们使用 Buffer 存储文件数据,并将其存储在 files 对象中。接着,我们将 files 和 fields 对象存储在 request.body 中。

方案二:删除 Koa-BODY 中间件默认的文件上传检测选项

我们可以通过删除文件上传检测选项来解决这个问题。以下是示例代码:

----- --- - ---------------
----- ------- - --------------------
----- --- - --- ------

-----------------
  ---------- -----
  ----------- -
    --------------- -----
    ---------- -----
    -- ---------- -----
    ------------ ------ ----- -- ------- -- ------
  -
----

------------- ----- -- -
  ------------------------------ 
  -- -- - ------- --- ------ -- -
---

-----------------

在这个示例代码中,我们将 Koa-BODY 的 onFileBegin 配置项设置为判断是否存在 name 或 file,如果这两个属性都不存在,则返回 true。这种方式将禁用 Koa-BODY 中间件的文件上传检测,但不是很安全。

结论

在处理 Koa 中的文件上传时,我们有两种解决方案。方案一手动处理请求,获取 files 和 fields,并存储在 request.body 对象中。方案二是禁用 Koa-BODY 中间件的文件上传检测选项,但这种方式并不是很安全。无论选择哪种方式,我们都应该根据实际需求进行选择。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/670fc7295f5512810267422d