WordPress无法上传图片提示Web服务器无法为该图像生成响应式图像大小的解决办法

AI 智能摘要
升级WordPress 7.1后,文章编辑器传图竟然报错“无法生成响应式图像”,后台媒体库却传得好好的。问题根源是前端裁剪图像时用到的blob:链接被网站CSP策略拦了。解决方案其实很简单,往functions.php加上一行过滤器就能彻底禁用前端预处理,把上传恢复到传统后端直传模式,或者把CSP响应头上的connect-src改成允许blob:和data:。改完记得清一下缓存,按Ctrl+F5刷新编辑器就搞定了。

昨天把手头的一个主力站顺手升级到了WordPress7.1,顺带把子比主题也拉到了最新的9.1版本。原本以为这次升级平淡无奇,前台页面、会员中心、各种自定义小工具都跑得飞起,结果今天打开文章编辑后台准备发篇新教程,刚插入一个图片区块点上传,当头就挨了一棒子。

后台直接弹出一行深红色的大字,提示说:Web服务器无法为该图像生成响应式图像大小。请在上传前将其转换为JPEG或PNG格式。如下图

图片[1]-WordPress无法上传图片提示Web服务器无法为该图像生成响应式图像大小的解决办法-主题铺

当时我就纳闷了,我上传的明明就是标准到不能再标准的PNG和JPG截图,怎么就格式不合规了?更诡异的是,我退回到WordPress后台的媒体库,直接点添加多媒体文件,一模一样的图片咔咔几下全传上去了,完全没有任何毛病,并且通过对象存储插件秒同步到了我的腾讯云COS桶里。既然媒体库能传,说明服务器的PHP环境、GD库、Imagick扩展以及对象存储配置统统没问题。问题显然出在文章编辑器的前端逻辑里。

顺藤摸瓜:控制台里的CSP真凶

碰到这种前后台行为不一致的玄学问题,直接按F12打开浏览器控制台看报错是最管用的。果然,在Console标签页里,满屏幕刷的全是深红色的Content Security Policy安全拦截警报。

报错信息非常明确,核心指引集中在这两行:
Connecting to blob:https://www.zhutipu.com/… violates the following Content Security Policy directive: connect-src *. Note that * matches only URLs with network schemes (http, https, ws, wss), or URLs whose scheme matches self scheme. The scheme blob: must be added explicitly. The action has been blocked.

往堆栈下面一看,全是worker.min.js、getVips、resizeImage这套东西在狂抛异常。

老站长这时候就该反应过来了。WordPress从很早开始就尝试在古腾堡编辑器里搞所谓的前端体验优化,到了WordPress7.1更是变本加厉,直接默认给文章编辑器接管了一套基于WebAssembly和libvips的本地客户端图像预处理机制。

说白了,以前你在文章里丢一张大图,浏览器会老老实实把原图丢给后端PHP去切图生成各种缩略图尺寸。现在的机制变了,只要你在文章编辑页上传图片,它会先拉起一个前端Web Worker后台线程,试图在浏览器本地把图片尺寸处理好,然后再上传。

在处理图片流的时候,浏览器生成的是blob:https开头的临时内存伪协议链接。倒霉就倒霉在很多站长跟我一样,为了网站安全,在Nginx、OpenLiteSpeed或者腾讯云EO、Cloudflare等边缘CDN上配置了CSP安全策略,里边写了connect-src *规则。

按照W3C的标准规范,通配符星号默认只匹配http、https、ws、wss这类网络协议,压根就不包含blob:和data:这类内存伪协议。于是前端线程在试图读取处理图片时,被浏览器自身的安全策略硬生生给拦腰掐断了。Web Worker崩溃罢工,古腾堡编辑器拿不到本地处理后的数据,转头就给你报了一个莫名其妙的假错误,把锅甩给Web服务器不支持格式。而在媒体库页面,上传走的是传统的后端接口,根本不触发前端WebAssembly切图,所以媒体库才会安然无恙。

为什么之前网传的过滤代码统统失效了

很多遇到这个坑的老铁,第一反应大概是去百度或者问老模型,搜出来的答案基本都是让你往functions.php里塞一段代码,去拦截block_editor_settings_all过滤钩子,把imageEditing或者clientSideMediaProcessing设为false。

老实说,如果是在之前的过渡测试版本,这个方案可能有用。但WordPress7.1对这块底层逻辑进行了重构,官方把客户端处理模块彻底剥离成了一个全局独立功能,原来的编辑器设置项根本管不到这个深度。

彻底根除问题的实测方案

搞清楚底层机制之后,解决这道难题其实有两种途径。

第一种方案是直接干掉前端预压缩,这也是我最推荐所有配置了对象存储的站长使用的做法。

咱们做网站动静分离,本身就挂了腾讯云COS或者阿里云OSS,后台又装了专门的云存储插件来负责云端智能切图、WebP转换和CDN分发。既然所有脏活累活都交给云端处理了,浏览器前端搞二次预处理纯属脱裤子放屁,不仅耗费访客电脑的CPU,还容易产生各种环境兼容性故障。

WordPress7.1官方为此专门提供了一个精准的全局控制过滤器。我们只需要打开当前子比主题或者子主题目录下的functions.php文件,在最底部追加下面这一行核心过滤代码:

/**
 * 彻底禁用 WordPress 7.1 客户端 WebAssembly/libvips 图像预处理
 * 强制所有古腾堡编辑器图片上传走传统服务器端流程(与媒体库保持完全一致)
 */
add_filter( 'wp_client_side_media_processing_enabled', '__return_false' );

这行代码一下去,相当于直接从系统根子上关闭了浏览器端Web Worker的本地切图逻辑。文章编辑器上传图片的行为会瞬间降级退回到最稳妥的传统模式,上传链路跟媒体库完全拉齐,直接走后端接口直传并送入腾讯云COS,blob内存读取被绕开,那个CSP报错自然也就灰飞烟灭了。

如果你非要保留浏览器本地切图这个功能,那就只能走第二种方案:修改你的CSP安全策略响应头。

你需要排查你的服务器配置(比如宝塔面板里的Nginx站点配置、OpenLiteSpeed的vhost配置、网站根目录的.htaccess),或者看看腾讯云EO、Cloudflare等CDN边缘规则里的HTTP响应头重写。找到Content-Security-Policy这一项,看看里面的connect-src是怎么写的。

只要把原本的规则:
connect-src *;
调整为把伪协议显式放行的格式:
connect-src * blob: data:;

这样浏览器知道了blob链接属于合法调用,Web Worker就能正常读取内存中的切片数据,报错同样能够解决。

避坑提醒

改完代码或者调整完响应头之后,记得去LiteSpeed Cache插件后台把全站缓存清空一次。如果你服务器启用了OPcache,最好顺便重载一下PHP服务,确保新的代码被服务器立即执行。

最关键的一步是回到文章编辑页面时,一定要在浏览器上按Ctrl+F5执行一次强制硬刷新,或者直接开一个浏览器无痕窗口去测试。因为浏览器本地对编辑器的JS脚本和之前的CSP策略是有强缓存的。缓存清掉之后再往文章里丢一张大图,那种丝滑上传秒传的感觉是不是又回来了?

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容