文章添加页面,粘贴图片到编辑框,返回html解析

2026-09-12 · 193 阅读
文章添加页面, 截图后,粘贴图片到编辑框,有时候会出现如图的提示,这是什么原因?如果超时或者oss 服务器故障,会返回什么?
Unexpected token'<', "<html>
<he"... is not valid JSON
OSS 服务层的故障都会兜成 JSON,不会产生 HTML。截图里 <html> 换行后 <he… 的格式正是 nginx 默认错误页(<html>\r\n<head><title>…) 一、那段英文是怎么冒出来的 前端粘贴上传的代码(article-editor.js)是无条件按 JSON 解析的: fetch(...).then(r => r.json()) fetch 只有在连不上(断网/DNS/CORS)时才会走 catch;只要服务器有任何 HTTP 响应回来——哪怕是 502、504、413 的 HTML 错误页——fetch 都算成功,然后 .json() 去解析 <!DOCTYPE html><html><head>…,于是抛出: Unexpected token '<', "<he"… is not valid JSON 这个异常被 catch 接住,alert 原样显示出来。所以它的含义不是"图片有问题",而是"服务器这次根本没回 JSON"。 二、哪些环节会返回 HTML(以及各自长什么样) 你们上传要经过四跳,每一跳的失败形态不同: 失败环节 状态码 返回内容 典型原因 ① nginx 请求体超限 413 nginx HTML 错误页 client_max_body_size 默认仅 1MB,截图 PNG 很容易超 ② nginx → PHP-FPM 502 / 504 nginx HTML 错误页 FPM 挂了/连接数满(502);PHP 执行超过 fastcgi_read_timeout(默认60秒,504) ③ PHP → 远程 OSS curl 30秒超时 JSON(已兜底) OssService 返回 {"code":0,"msg":"请求 OSS 失败:…"},不会出英文报错 ④ 后台登录过期 302→200 登录页 HTML 见下,这是"有时候"的高频原因 注意 ③:你们代码其实已经设计得不错,OSS 超时/宕机/返回异常都在 PHP 里兜成 JSON。所以只要看到 HTML,一定是 PHP 之外的环节(nginx、FPM,或重定向) 三、有办法处理,分两层 方案 A:前端"防御性解析"(最治本,改动小) 思路是不要假设响应一定是 JSON,解析前先验身: 先看 response.ok 和 Content-Type:不是 application/json 就不解析,按状态码翻译成人话——413="图片太大"、504="服务器超时,请重试"、200但HTML="登录已过期,请刷新重登"; 给 fetch 套 AbortController 设前端超时(fetch 本身没有超时机制); catch 里再兜一层:即使解析报错,也提示"上传失败,请重试",而不是把 Unexpected token 原文甩给用户; 502/504 多为瞬时故障,可自动重试 1 次。 这样不管后端吐什么,用户看到的永远是明确的中文提示。 方案 B:nginx 把错误也吐成 JSON(运维侧,不动业务代码) 在上传接口的 location(或后台 API 统一前缀)上用 error_page 兜底: nginx error_page 413 502 503 504 = @upload_err; location @upload_err { default_type application/json; return 500 '{"code":0,"msg":"服务器繁忙或超时,请稍后重试"}'; } 要点:只对接口路径做,别全局改,否则网页出错时用户也会下载一坨 JSON。配合把这条链路上的参数对齐,让"谁先超时"有明确分工: client_max_body_size 调到略大于业务限制(代码里正文图是 5MB,nginx/PHP 都应 ≥5MB 留点余量); 超时梯度建议 nginx fastcgi_read_timeout > PHP max_execution_time > OSS 的 CURLOPT_TIMEOUT(30s)。现在 OSS 在 SSL 证书失败时会重试一次,最坏 30×2=60 秒,恰好顶着 nginx 默认的 60 秒,边界上可能互相打架,值得留意; PHP 的 upload_max_filesize、post_max_size 也要和 nginx 一致,否则 PHP 超限返回的又是另一种形态。 方案 C:架构层(了解即可) 截图通常只有几百 KB,频繁 504 说明瓶颈在服务器↔OSS 那一跳或 FPM 承载力。长期可以考虑前端拿签名直传 OSS,少一跳转发,从根上消除"我们的服务器等远程 OSS"的超时;大文件再加分片和进度条。但这改动大,不是现在必须做的。 四、下次复现时怎么 10 秒定位 F12 → Network → 点那条 uploadImage 请求: 413 → 体积超限,调 nginx/PHP 大小; 504/502 → 看 /var/log/nginx/error.log 同时段是否有 upstream timed out,再看 PHP-FPM slow log; 200 + HTML → 看响应体标题,是登录页就是 session 过期; 状态 (failed) 没状态码 → 连接被直接掐断(网络/防火墙)。 小结:能处理,而且不用动业务逻辑——核心就两件事:前端解析前先判断响应类型,nginx 给接口路径加 JSON 版 error_page;另外建议优先排查 413(截图超 1MB)和登录过期这两个"有时候"最常见的真凶。
责任编辑:gl 更新:2026-09-12 16:45:43