本文详解为何在使用 XMLHttpRequest + FormData 发送含 HTML 片段(如 )的 JSON 字符串时,服务端接收数据出现标签丢失、字符串被截断的问题,并提供安全、标准的解决方案。
本文详解为何在使用 xmlhttprequest + formdata 发送含 html 片段(如 ``)的 json 字符串时,服务端接收数据出现标签丢失、字符串被截断的问题,并提供安全、标准的解决方案。
在前端通过 FormData 提交 JSON 字符串时,若该 JSON 内部嵌套了未转义的 HTML 片段(例如 "text":["testStarttestEnd"]),极易因特殊字符(尤其是 , ', ")未被正确编码,导致服务端解析异常或数据截断——这正是你观察到 "testStarttestEnd" 的根本原因。
关键误区在于:FormData.append(key, value) 并不会自动对字符串内容做 URL 编码或 JSON 序列化。当你直接传入一个已含 HTML 标签的原始 JSON 字符串(如 e.target.result),浏览器会将其作为普通文本字段提交。而部分服务器环境(尤其搭配某些 PHP 配置或中间件)可能对 做预处理(如尝试解析为 HTML 或过滤标签),或在解析 multipart/form-data 边界时因未转义引号/尖括号引发字段截断。
✅ 正确做法是:始终确保传输的是合法、自洽的 JSON 字符串,且服务端按 JSON 协议解析。具体分三步:
-
前端发送前:显式序列化并编码
即使 e.target.result 已是字符串,也需确认其结构合法;更稳妥的做法是先 JSON.parse() 再 JSON.stringify(),强制标准化:reader.onload = (e) => { try { const rawJson = e.target.result; // 验证并标准化 JSON(可选但推荐) const parsed = JSON.parse(rawJson); const safeJsonString = JSON.stringify(parsed); // 确保引号、斜杠、尖括号等被正确转义 const fdata = new FormData(); fdata.append("json", safeJsonString); // ✅ 传入已转义的 JSON 字符串 const request = new XMLHttpRequest(); request.addEventListener("load", () => { console.log("Server response:", request.response); }); request.open("POST", "import_export_quiz.php"); request.send(fdata); } catch (err) { console.error("Invalid JSON in file:", err); } }; -
后端接收时:严格按 JSON 解析
不要直接使用 $_POST["json"](它可能被 PHP 自动解析为数组或损坏),而应从原始输入流读取并解码:// import_export_quiz.php $jsonInput = file_get_contents('php://input'); // 或:$jsonInput = $_POST['json'] ?? ''; $data = json_decode($jsonInput, true); if (json_last_error() !== JSON_ERROR_NONE) { http_response_code(400); echo json_encode(['error' => 'Invalid JSON']); exit; } // ✅ 此时 $data 是完整、正确的 PHP 数组,HTML 标签保留完好 -
响应返回:统一用 json_encode() 输出
避免直接 echo $jsonInput(可能触发 XSS 或编码问题):header('Content-Type: application/json; charset=utf-8'); echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
⚠️ 补充说明:
- Base64 方案虽可行,但非最佳实践——它增加传输体积、绕过标准 JSON 流程,掩盖了根本问题;仅当必须兼容极旧环境时考虑。
- 永远不要依赖 $_POST 直接获取 JSON 字符串:PHP 的 $_POST 是为 application/x-www-form-urlencoded 设计的,对 multipart/form-data 中的 JSON 字段支持不稳定。
- HTML 标签本身无需额外 HTML 实体编码(如 <),只要 JSON 字符串内部已正确转义(JSON.stringify 自动完成),即可安全传输。
总结:问题本质是「混淆了表单字段值与 JSON 数据的语义边界」。坚持「前端 JSON.stringify() → 后端 json_decode(file_get_contents('php://input'))」这一黄金组合,即可 100% 保留 HTML 片段、数组结构及所有特殊字符,无需 hack 式规避。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











