Node中Unexpected end of form 錯誤

文章目錄

  • Unexpected end of form 錯誤
      • 為什么 `app.use(upload.any())` 會導致 `Unexpected end of form` 錯誤?
    • 1. 主要問題分析
      • `app.use(upload.any())` 的問題
      • 錯誤場景
    • 2. 解決方案
      • ? 方案 1:僅在需要文件上傳的路由使用 Multer(推薦)
      • ? 方案 2:檢查前端請求是否正確
      • ? 方案 3:增加錯誤處理
    • 3. 調試方法
      • 1. 檢查請求頭
      • 2. 使用 `curl` 測試
    • 總結

Unexpected end of form 錯誤

為什么 app.use(upload.any()) 會導致 Unexpected end of form 錯誤?

這個錯誤通常發生在 Multer 中間件配置不當前端請求數據不完整 的情況下。以下是可能的原因和解決方案:


1. 主要問題分析

在這里插入圖片描述

app.use(upload.any()) 的問題

  • upload.any() 會全局解析所有 multipart/form-data 請求,即使某些請求并不需要文件上傳。
  • 如果某個請求 沒有正確發送 multipart/form-data 數據(比如普通的 application/json 請求),Multer 仍然會嘗試解析,導致 Unexpected end of form 錯誤。

錯誤場景

  1. 前端未正確發送 FormData

    • 如果前端發送的是 JSON 數據,但后端仍然用 upload.any() 解析,就會報錯。
    • 示例錯誤請求
      // ? 錯誤的請求方式(JSON 數據,但后端期望 FormData)
      fetch("/api/upload", {method: "POST",body: JSON.stringify({ name: "test" }), // 不是 FormDataheaders: { "Content-Type": "application/json" },
      });
      
    • 正確方式
      // ? 正確的 FormData 請求
      const formData = new FormData();
      formData.append("file", fileInput.files[0]);
      fetch("/api/upload", {method: "POST",body: formData, // 瀏覽器會自動設置 Content-Type: multipart/form-data
      });
      
  2. Multer 全局中間件與特定路由沖突

    • 如果你在某些路由 單獨使用 upload.single()upload.array(),而全局又用了 upload.any(),可能會導致 Multer 解析兩次,從而報錯。

2. 解決方案

? 方案 1:僅在需要文件上傳的路由使用 Multer(推薦)

不要全局使用 app.use(upload.any()),而是僅在需要文件上傳的路由單獨使用 Multer:

const express = require("express");
const multer = require("multer");
const upload = multer(); // 不存儲到磁盤,僅解析const app = express();// ? 刪除全局中間件
// app.use(upload.any());// ? 僅在需要文件上傳的路由使用 Multer
app.post("/upload", upload.single("file"), (req, res) => {console.log(req.file); // 上傳的文件res.send("上傳成功");
});// 普通 JSON 請求不會受影響
app.post("/api/data", (req, res) => {res.json({ message: "OK" });
});

優點

  • 避免 Multer 解析不需要文件上傳的請求。
  • 減少潛在的錯誤。

? 方案 2:檢查前端請求是否正確

確保前端發送的是 multipart/form-data 請求:

// 前端代碼示例(React/Axios)
const formData = new FormData();
formData.append("file", file); // 確保字段名和 Multer 配置一致axios.post("/api/upload", formData, {headers: {"Content-Type": "multipart/form-data", // 瀏覽器通常會自動設置,但可以手動加},
});

檢查點

  • 是否真的發送了文件?
  • 字段名是否匹配(如 upload.single("file") 要求前端必須用 formData.append("file", ...))?

? 方案 3:增加錯誤處理

在 Multer 解析失敗時,返回更友好的錯誤信息:

app.post("/upload", upload.single("file"), (req, res) => {// 成功處理
}, (err, req, res, next) => {if (err instanceof multer.MulterError) {return res.status(400).json({ error: "文件上傳錯誤" });} else if (err) {return res.status(500).json({ error: "服務器錯誤" });}next();
});

3. 調試方法

1. 檢查請求頭

在 Chrome DevTools Network 面板查看請求:

  • 正確的 multipart/form-data 請求
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXXXX
    
  • 錯誤的請求
    • 如果 Content-Typeapplication/json,但后端用 Multer 解析,就會報錯。

2. 使用 curl 測試

# 正確上傳文件
curl -X POST -F "file=@test.jpg" http://localhost:3000/upload# 錯誤示例(發送 JSON 數據)
curl -X POST -H "Content-Type: application/json" -d '{"name":"test"}' http://localhost:3000/upload

如果第二個命令報錯,說明 Multer 無法解析非 multipart/form-data 請求。


總結

問題解決方案
全局 app.use(upload.any()) 導致所有請求被解析改用路由級 upload.single()
前端未發送 FormData確保使用 FormData 并正確設置字段名
Multer 解析失敗增加錯誤處理中間件
請求頭 Content-Type 錯誤檢查瀏覽器是否自動設置 multipart/form-data

推薦做法

  1. 移除 app.use(upload.any()),僅在需要的地方使用 Multer。
  2. 確保前端發送正確的 FormData
  3. 增加錯誤處理,避免服務器崩潰。

multipart/form-data` |

推薦做法

  1. 移除 app.use(upload.any()),僅在需要的地方使用 Multer。
  2. 確保前端發送正確的 FormData
  3. 增加錯誤處理,避免服務器崩潰。

這樣應該能解決 Unexpected end of form 錯誤! 🚀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90111.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90111.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90111.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

通過Curtain 解決方案保障BIM模型安全共享—建筑業的防泄密實戰

某跨海大橋項目突發數據泄露事件:主橋鋼結構的BIM模型被外泄,核心參數流入競爭對手手中,導致項目風險評估升級。調查發現,泄漏源頭是一名施工方的項目經理。盡管BIM系統已經能夠控制哪些人可以閱讀、修改、甚至下載資料的權限&…

ULVAC愛發科RFS03D RF POWER SUPPLY INSTRUCTION MANUAL RF射頻電源

ULVAC愛發科RFS03D RF POWER SUPPLY INSTRUCTION MANUAL RF射頻電源

暑假算法日記第三天

目標?:刷完靈神專題訓練算法題單 階段目標📌:【算法題單】滑動窗口與雙指針 LeetCode題目: 3439. 重新安排會議得到最多空余時間 I2134. 最少交換次數來組合所有的 1 II1297. 子串的最大出現次數2653. 滑動子數組的美麗值1888. 使二進制字符…

了解業務分析技術梗概

業務分析技術 以下基于BABOK V3框架,結合業務分析師(BA)的實際工作場景,系統梳理50項業務分析技術、常用工具、學習路徑及文檔應用指南。內容綜合BABOK官方標準及行業實踐,旨在提升BA的工作效能。 一、BABOK V3 技術體…

小紅的數字刪除 - 牛客

小紅的數字刪除 題目不難&#xff0c;忽略了一個 corner case&#xff0c;導致我在某次面試沒有 AK。 10003 對于這個 case&#xff0c;只考慮前導零 全部刪除是不對的&#xff0c;剩下的 3 也不能刪。 void solve(){string s;cin >> s;int res0;vector<int> a(…

Linux網絡: socket初識

一些概念 簡單了解一下TCP,UDP這兩個協議&#xff0c;和一些概念 TCP與UDP 學校教過TCP是 傳輸層協議有連接可靠傳輸面向字節流 而UDP是 傳輸層協議無連接不可靠傳輸面向數據報 當時完全不知道這些什么意思 網絡字節序 網絡通信&#xff0c;要接收和發送數據。我們知道…

AI時代的彎道超車之第二十七章:AI技術的發展方向

在這個AI重塑世界的時代,你還在原地觀望嗎?是時候彎道超車,搶占先機了! 李尚龍傾力打造——《AI時代的彎道超車:用人工智能逆襲人生》專欄,帶你系統掌握AI知識,從入門到實戰,全方位提升認知與競爭力! 內容亮點: AI基礎 + 核心技術講解 職場賦能 + 創業路徑揭秘 打破…

RabbitMQ用法的6種核心模式全面解析

文章目錄**一、RabbitMQ核心架構解析**1. AMQP協議模型2. 消息流轉原理**二、六大核心用法詳解****1. 簡單隊列模式&#xff08;Hello World&#xff09;****2. 工作隊列模式&#xff08;Work Queues&#xff09;****3. 發布/訂閱模式&#xff08;Pub/Sub&#xff09;****4. 路…

深入協程調試:協程調試工具與實戰

本文系統梳理主流協程調試工具&#xff0c;結合完整代碼示例與實戰技巧&#xff0c;助你高效解決異步編程難題一、協程調試的核心挑戰 協程的非線性執行流是調試的最大挑戰&#xff1a; 傳統斷點調試難以追蹤協程切換堆棧信息不完整或丟失上下文并發競爭條件難以復現 #mermaid-…

Git 日常開發實戰命令大全

&#x1f9f0; Git 日常開發實戰命令大全 本文整理了 Git 在日常開發中高頻使用的命令集合&#xff0c;覆蓋從基礎操作到進階技巧的完整流程&#xff0c;方便留存查閱&#x1f440; &#xff0c;最后附上所有指令。其中內容包括&#xff1a; ? 本地倉庫管理&#xff1a;添加文…

力扣 hot100 Day37

25. K 個一組翻轉鏈表 給你鏈表的頭節點 head &#xff0c;每 k 個節點一組進行翻轉&#xff0c;請你返回修改后的鏈表。 k 是一個正整數&#xff0c;它的值小于或等于鏈表的長度。如果節點總數不是 k 的整數倍&#xff0c;那么請將最后剩余的節點保持原有順序。 你不能只是…

【力扣 中等 C】516. 最長回文子序列

目錄 題目 解法一 題目 待添加 解法一 int max(int a, int b) {return a > b ? a : b; }int longestPalindromeSubseq(char* s) {const int len strlen(s);int dp[len];for (int i len - 1; i > 0; i--) {dp[i] 1;int leftDown;if (i 1 < len) {leftDown dp…

DAY 54 Inception網絡及其思考

知識點回顧&#xff1a; 傳統計算機視覺發展史&#xff1a;LeNet-->AlexNet-->VGGNet-->nceptionNet-->ResNet 之所以說傳統&#xff0c;是因為現在主要是針對backbone-neck-head這樣的范式做文章 inception模塊和網絡特征融合方法階段性總結&#xff1a;逐元素相加…

1. 微服務架構演進:從單體到SpringCloud

想象一下,你剛剛花了一個下午在生產環境下部署一款單體應用,結果因為一個微小的配置變動,整個系統宕機,大量用戶投訴蜂擁而至。運維緊急回滾,開發又要加班定位問題……這并非孤立事件,而是單體架構在規模和復雜性增長后常見的“連鎖反應”。 一、單體架構:簡單之始,復雜…

Charles 中文版抓包工具詳解:加速 API 調試與網絡問題排查

隨著技術的不斷發展&#xff0c;開發者面臨的任務日益復雜&#xff0c;特別是在調試和優化API接口時。確保應用的網絡請求在各種環境下的穩定性和高效性是提高用戶體驗的關鍵。Charles抓包工具作為一款強大的網絡調試工具&#xff0c;能夠幫助開發者精確捕獲HTTP/HTTPS流量&…

巔峰對話:文心4.5 vs DeepSeek R1 vs 通義Qwen3.0 深度評測

國產大模型三強爭霸&#xff0c;誰主沉浮&#xff1f; 2025年是中國大模型開源爆發之年——百度文心4.5系列橫空出世&#xff0c;阿里通義Qwen3.0登頂開源榜首&#xff0c;而DeepSeek R1在編程領域悄然登頂。 三大技術路線齊頭并進&#xff0c;卻走出了截然不同的道路。 在這…

Linux運維安全新范式:基于TCPIP與SSH密鑰的無密碼認證實戰

文章目錄 前言1. Linux 生成SSH秘鑰對2. 修改SSH服務配置文件3. 客戶端秘鑰文件設置4. 本地SSH私鑰連接測試5. Linux安裝Cpolar工具6. 配置SSHTCP公網地址7. 遠程SSH私鑰連接測試8. 固定SSH公網地址9. 固定SSH地址測試 前言 在云原生架構全面滲透企業IT體系的當下&#xff0c;…

行階梯形矩陣和行最簡形矩陣的區別

目錄 0、主元 一、行階梯形矩陣&#xff08;REF&#xff09; 特點&#xff1a; 二、行最簡形矩陣&#xff08;RREF&#xff09; 特點&#xff1a; 0、主元 主元是&#xff1a;該行最左側的非零元素??&#xff08;即第一個不為零的元素&#xff09;。 一、行階梯形矩陣&…

力扣 3258 統計滿足 K 約束的子字符串數量 I 題解

此題不評價&#xff0c;有點意思&#xff0c;我在次以兩種語言python 和c&#xff0c;用兩種相反的思路寫&#xff0c;注意細節不同。 原題鏈接3258. 統計滿足 K 約束的子字符串數量 I - 力扣&#xff08;LeetCode&#xff09; 法一&#xff0c;c&#xff0c;先統計出不符合的…

創意Python愛心代碼

創意Python愛心代碼分享的技術文章大綱 引言 簡述Python在圖形繪制和創意編程中的優勢介紹愛心代碼在編程社區中的受歡迎程度本文涵蓋的創意愛心代碼示例及其技術亮點 基礎愛心繪制 使用數學公式和turtle庫繪制簡單愛心代碼示例&#xff1a; import turtle def draw_heart…