禅道上传限制如何修改?PHP与Nginx三层配置实战指南
发布时间:2026/10/16 10:10:13 锦皓数字建站

1. 这需求是怎么来的先弄清楚禅道的上传限制卡在哪了做运维或者当项目管理工具的管理员迟早会撞上这个问题。团队用禅道管项目跑了一段时间同事突然反馈说附件传不上去了一看提示才知道是文件太大。去禅道后台翻了半天发现设置界面里根本没有“允许上传大小”这个选项。这时候才意识到禅道的上传限制压根就不是它自己说了算而是被底层的 PHP 配置和 Web 服务器配置双重卡住的。我在实际排查过程中发现绝大多数人第一次遇到这个问题时都会钻进禅道的源码或者数据库配置表里找答案其实方向完全错了。禅道本身对上传大小确实有一些控制但那是基于 PHP 层接收到的请求参数做二次校验真正决定能不能传上去的核心在 PHP 的upload_max_filesize、post_max_size以及 Nginx 或 Apache 的请求体大小限制这三层。这三层只要有一层没放开你就算把禅道后台翻个底朝天也没用。所以这篇文章想把整个链路讲清楚为什么你改了 PHP 配置还是传不了大文件Nginx 那层到底应该怎么配以及改完之后有哪些细节容易忽略。按我给出的顺序走一遍基本能解决 99% 的上传限制问题。顺带说一句这套方法不仅适用于禅道其它跑在 Linux PHP Nginx或 Apache环境下的 Web 应用比如部分开源网盘、表单系统、企业 Wiki原理都一样。你把这个思路吃透了以后碰到任何“改了配置但是上传限制没变”的怪问题都能套用这套排查逻辑。2. 上传限制的完整链路PHP、Nginx、禅道各自管什么2.1 三层限制模型缺一层就前功尽弃要改禅道的文档上传限制首先得在心里建立一张“链路图”。一次文件上传请求从浏览器发出到最终存到禅道的data/upload目录下会依次经过三到四道关卡每一道关卡都设置了自己的上限第一道是 Web 服务器层。如果你用的是 Nginx它有一个client_max_body_size参数默认值是 1m也就是 1MB。这个参数限制的是整个 HTTP 请求体的大小不仅仅是文件本身还包括 POST 请求里的表单字段、JSON 数据等。这一层是最容易忽略的因为它在 Nginx 配置里很多人改完 PHP 就以为完事了结果 Nginx 直接返回 413 Request Entity Too Large一脸懵。第二道是 PHP 层。PHP 有两个关键参数一个是upload_max_filesize单独限制单个上传文件的大小PHP 默认值是 2M另一个是post_max_size限制整个 POST 请求体的总大小默认值是 8M。这两个参数必须一起看因为就算你把upload_max_filesize改成了 20M但post_max_size没动PHP 会认为整个 POST 数据超过了 8M一样会拒绝接收。更坑的是PHP 在这种情况下返回的错误信息往往不够明确让你以为是文件格式问题或者禅道的问题实际上纯粹是post_max_size没改够。第三道是 PHP 脚本执行时间和内存限制。当一个文件从磁盘读入 PHP 内存再写入目标目录时会占用脚本执行时间和内存。如果文件太大PHP 的max_execution_time不够用脚本会在处理过程中被强制终止表现就是上传进度走完了但最终提示超时失败。另外memory_limit如果设置得太低大文件在上传过程中也可能触发内存耗尽错误。第四道才是禅道自身的应用层校验。禅道在接收到上传请求后会读取 PHP 的配置值来生成前端提示并且在后端对文件大小、扩展名做二次校验。如果文件太大哪怕 PHP 和 Nginx 都放行了禅道自己的校验逻辑也会拒绝。但异步上传场景下一部分远程文件或大分块文件会绕过一些校验这里先不展开后面在常见问题里再详细说。2.2 为什么只改一处往往会翻车网上很多教程只让你改 PHP 的upload_max_filesize改完重启php-fpm就结束了结果实测下来根本没生效。原因很简单Nginx 那一层的 1MB 限制还死死挡在前面。你上传一个 5MB 的文件Nginx 直接返回 413PHP 层见都没见到这个请求你改 PHP 有什么意义反过来如果只改 Nginx 不放宽 PHP请求能到 PHP 层了但 PHP 的upload_max_filesize还是 2M照样拒绝。所以正确的思路是从外到内逐层放开每一层设置的数值还要保持一定的递进关系避免两层之间出现新的瓶颈。我个人习惯的做法是Nginx 的client_max_body_size比 PHP 的post_max_size稍大一点PHP 的post_max_size又比upload_max_filesize大一点。原因在于upload_max_filesize只管单个文件但一个请求可能同时传多个文件加上表单里的其它文本字段整个 POST 体积会比单个文件大。如果post_max_size只是刚好等于upload_max_filesize那么一次传两个大文件的时候就会失败。遵循“Nginx PHP POST PHP 单文件”的递进原则能避免很多莫名其妙的边界问题。还有一个衍生问题PHP 的post_max_size如果设置得很大意味着 PHP 允许接收大体积的 POST 请求这会带来一定的安全风险比如恶意用户构造超大请求体造成服务器资源被占满。所以这层配置并不是越大越好而是根据实际业务需求取一个合理的值。正常项目团队传文档、传压缩包单文件几 MB 到几十 MB 是常态可以设到 100M 或 200M如果还有视频、镜像包这类超大文件那就得考虑分块上传或者单独走对象存储了。3. 实操之前的准备工作先搞清楚几份配置文件在哪3.1 定位 PHP 配置文件在动手修改之前第一步是找到 PHP 的配置文件。不同发行版、不同安装方式配置文件的位置差异很大。我见过用源码编译安装的 PHP配置文件在/usr/local/php/etc/php.ini用 yum 或 apt 安装的一般在/etc/php.ini还有的发行版会拆分成/etc/php/7.x/cli/php.ini和/etc/php/7.x/fpm/php.ini注意区分 CLI 和 FPM 用的是不同的配置文件。最靠谱的方法不是靠猜而是执行命令查当前加载的配置文件路径。在终端运行php --ini或者查询当前生效的上传相关参数值php -i | grep -E upload_max_filesize|post_max_size如果是通过 php-fpm 运行的还可以创建一个临时 PHP 文件输出phpinfo()来查看实际加载的配置但更推荐用命令行直接查。这里有一个容易踩的坑有些环境里php --ini查到的是 CLI 的配置路径而 Web 请求实际走的是 php-fpm 或 Apache 的libphp模块两者加载的php.ini可能不是同一个。比如某次我的模块化部署里CLI 走/etc/php.ini而 php-fpm 却加载了/etc/php-fpm.d/php.ini下面覆盖的参数。仅改 CLI 的配置根本不影响 Web 侧。所以最好先确认你的 Web 环境是php-fpm还是mod_php再对应找配置。还有一个更隐蔽的情况php-fpm的 pool 配置里通常在/etc/php-fpm.d/www.conf可以直接用php_admin_value或php_value形式覆盖upload_max_filesize、post_max_size等参数。这个优先级高于php.ini但又低于目录下的.htaccess如果允许用php_flag。如果php.ini里已经改成 200M但www.conf里还写着一行php_value upload_max_filesize 8M那么实际生效的就是 8M。我在排查时遇到过不止一次这种情况所以每次改配置前都要全盘搜索一遍关键词grep -r upload_max_filesize /etc/php* /usr/local/php*把每一处出现的地方都看清才能确定真正的配置入口。3.2 定位禅道运行目录和 Nginx 配置禅道本身的安装位置也值得确认。一般禅道企业版的默认安装路径是/opt/zbox或者/www/zentaopms开源版通过源码部署的话常常放在 Web 根目录下比如/data/www/zentaopms。如果你不确定可以看 Nginx 的配置里的root指令指向哪里或者访问禅道登录页用浏览器的“查看源代码”看静态资源路径大致能推断出来。Nginx 配置文件的查找方式相对固定。在终端输入nginx -t可以校验配置语法同时会输出主配置文件路径。一般是/etc/nginx/nginx.conf。然后看它 include 了哪些子配置文件常见的模式是/etc/nginx/conf.d/*.conf以及/etc/nginx/sites-enabled/*。禅道对应的站点配置通常在某个以域名命名的 conf 文件里或者在/usr/local/nginx/conf/vhost/目录下。找到之后重点看server块内的配置client_max_body_size一般放在server或location块内。如果你找不到这个参数说明它没被显式设置那么默认值就是 1m。4. 核心实操步骤从 PHP 到 Nginx 再到禅道逐层放开4.1 修改 PHP 的 upload_max_filesize 和 post_max_size确定好配置文件的路径之后用你习惯的编辑器打开php.ini搜索以下三个参数upload_max_filesize 200M post_max_size 220M max_execution_time 600 memory_limit 512M参数的具体数值不需要完全照搬而是要根据你的实际业务来定。我自己的习惯是单文件上限设为 200Mpost 总上限设为 220M留 20M 的空间给表单字段和其它文本数据。max_execution_time从默认的 30 秒改成 600 秒因为大文件上传在服务器处理时需要一定的时间尤其是在磁盘 I/O 较慢或文件需要做安全检查的场景下。memory_limit至少提到 512MPHP 在接收和写入大文件时如果开了某些扩展比如做图片处理、解压校验内存消耗会明显上升。这里有个细节post_max_size必须大于upload_max_filesize。否则当用户一次上传多个文件时总大小可能超过post_max_size请求会被 PHP 直接拒绝。如果你不确定这两个值的倍数关系可以直接把post_max_size定为upload_max_filesize的 1.1 倍或 1.2 倍。修改完成后需要重启 php-fpm 才能生效。重启命令根据发行版不同有所区别systemctl restart php-fpm # 或者 service php-fpm restart如果你使用的是禅道自带的集成环境比如 zbox那么修改的不是系统 php-fpm而是禅道内置的 PHP 服务。这时候重启方式要换成禅道的控制脚本。切到 zbox 目录下./zbox restart或者用它提供的service.sh脚本。有人会忽略这一步改完php.ini就想当然地认为生效了实际上内置 PHP 的进程还跑着旧配置上传限制一点没变。4.2 修改 Nginx 的 client_max_body_sizePHP 改完之后接着解决 Nginx 层。在禅道对应的站点配置文件的server块内添加或修改一行client_max_body_size 220M;如果原本已经有这行配置直接改数字即可。注意单位m是小写表示兆字节也可以写成k、g。我的建议是放在server层级而不是某个location层级这样该站点下所有上传路径都覆盖到了。如果只放在某个location里比如location /api/其它路径的请求仍然受默认 1M 限制影响容易漏掉。改完配置后用命令检查语法nginx -t看到syntax is ok再执行重载nginx -s reload # 或者 systemctl reload nginx不要用nginx -s stop再启动这种方式会导致瞬间断连reload是平滑重载生产环境更安全。这里我再强调一个容易忽视的点如果禅道是跑在 Apache 环境下Nginx 那层就不存在对应的是 Apache 的LimitRequestBody或mod_security的规则。但绝大多数生产部署都是 Nginx php-fpm所以本文以 Nginx 为主线。4.3 禅道自身的配置文件与 UI 层提示到了这一层才轮到禅道自身。禅道并非没有上传大小限制只是它的限制值并不是从数据库读的而是直接读 PHP 的upload_max_filesize。换句话说你改完 PHP 后禅道后台的提示内容会自动跟着变。但有一个特殊情况禅道的配置文件/www/zentaopms/config/my.php里存在一个叫maxSize的配置项。某些版本的禅道把这个值写死在配置里前端 JS 在进行文件校验时会优先读取它。如果这个值没有同步更新就会出现一个诡异的现象大文件实际上传到了服务器但前端在上传开始前就拦截了提示“文件超大”实际上后端并没有拒绝。这种案例我遇到过好几次。解决方案是在my.php中找到类似这样的配置$config-file-maxSize 200;数字单位是 MB。将它调整到和 PHP 的upload_max_filesize一致或略小保存后刷新页面。纯开源版在某些版本中这个值可能不存在那就不用加只靠 PHP 配置即可。还有一点涉及附件存储路径的权限问题。禅道的附件默认存放在www/data/upload目录下。这个目录的归属用户必须和 php-fpm 运行用户一致否则上传的文件无法写入各个版本的禅道还会返回各自特有的错误提示。常见做法是设为 777chmod -R 777 /www/zentaopms/www/data/upload但要注意chmod -R 777只适合局域网或测试环境公网部署建议改为组权限或使用chown指定用户避免不必要的安全暴露。4.4 校验修改是否真的生效改完所有配置后不要急着让同事去试先自己验证一遍。最直接的方法是去禅道的“后台-系统设置-附件设置”页面看看显示的上传上限是否已经变成你期望的值。如果界面上的值没变说明某个配置没改对或者没重启成功。更严谨的做法是用命令行模拟请求。先生成一个测试文件dd if/dev/zero oftestfile.bin bs1M count150然后通过 curl 上传到这个测试文件观察响应码和响应时间curl -F filetestfile.bin http://你的禅道域名/index.php?mfilefupload如果返回正常说明上传链路已经通了。如果返回 413说明 Nginx 层没改对如果返回 500 或 PHP 警告说明 PHP 层配置有问题如果禅道返回业务错误码则可能卡在前端校验或者my.php的maxSize没改。这一步非常关键它能帮你快速定位是哪一层还没打开避免靠肉眼猜。5. 常见问题与排查技巧实录5.1 改了配置却提示“文件太大”或 413这是出现频率最高的问题。我已经在上文中提到了主要原因Nginx 的client_max_body_size没改或者没重启 php-fpm。但还有一种相对少见的原因有反向代理层在请求前面比如用了 CDN、云 WAF 或者另一层 Nginx。这种情况下你改的只是后端 Nginx前端代理层还有自己的请求体限制。排查方法是用 curl 直接打后端 IP绕过代理层测试如果绕过代理能正常上传问题就在代理层需要到代理的配置里同样放开client_max_body_size。还有一次我踩过一个奇葩坑服务器上有两个 Nginx 实例一个监听 80 端口做转发另一个监听 8080 端口处理 PHP。我改了后者的client_max_body_size但前者的转发层没改结果上传大文件时总是被前端的 Nginx 拦截。这种多实例场景在容器化部署里尤其常见nginx ingress 控制器、API 网关、负载均衡器都可能夹在中间每一层都需要检查。5.2 上传 200M 文件时提示“连接被重置”这个现象容易误导人。表面看是网络问题实际原因往往是 PHP 的max_execution_time超时。当服务器接收大文件后开始处理比如做安全检查、转移文件、生成缩略图这个处理过程耗时会超过max_execution_time的默认值PHP 会直接终止脚本。表现就是请求进行到一半时被重置浏览器无法收到正常响应。解决方案是把max_execution_time调大同时关注php-fpm的request_terminate_timeout参数。这个参数在www.conf或 pool 配置里默认可能是 0表示不限制但有些发行版会设置成 30 或 60 秒。如果你改了 PHP 的max_execution_time但没动这个参数它仍然会在超时后强制杀掉请求。我的建议是把request_terminate_timeout也设置成和max_execution_time相同或稍大一点避免因为这两个超时机制不同步而出现问题。5.3 内网上传没问题外网总失败内外网表现不一致大概率是代理层或防火墙的问题。外网请求经过的路径更长可能经过 CDN、云防火墙、网关等节点其中任何一层对请求体大小有限制都会导致上传失败。还有一种可能是链路中存在 TCP 超时或连接重置的节点大文件上传耗时较长更容易被中间节点切断。排查思路是分段测试先用内网 IP 直接上传确认应用层没问题再用公网域名上传看失败点在哪如果公网失败而内网成功借助抓包工具看是哪个节点返回的 TCP RST或者到 CDN/防火墙控制台看访问日志找到具体的拦截原因。这类问题没有统一的开配置指令只能顺着链路一层层排查。5.4 上传成功后文件损坏或只有部分内容这种问题在跨版本升级禅道或者迁移服务器后容易出现。原因一般是服务器本身的 PHP 配置文件没有错误但上传过程中因为 PHP 的post_max_size小于upload_max_filesize造成的。当post_max_size比文件实际体积小得多时PHP 不会完整接收报文体而是截断处理导致禅道拿到不完整的数据。表现出来就是文件能上传但传上去的文件大小比原本小不少。建议总是把post_max_size设置成大于upload_max_filesize的 1.2 倍这样就算用户同时上传多个大文件总和也不会轻易超过 POST 限制。5.5 修改后无任何变化的速查清单为了解决“改了什么但看起来没改”的情况我把自己的排查顺序做成了一张清单每次遇到这类问题就按顺序走一遍效率高很多PHP 配置文件路径是否正确CLI 和 FPM 是否共用同一个php.ini。是否在www.conf或php-fpm.d下面存在php_value或php_admin_value覆盖了php.ini的值。Nginx 站点配置里的client_max_body_size是否放在了正确的server或location块。有没有反向代理、CDN、负载均衡器在前面拦了一道。禅道config/my.php里的maxSize是否同步更新。改完配置后是否重启了正确的服务重启的是不是禅道内置的 PHP。附件上传目录的写权限是否正常。这七步走完绝大多数上传限制问题都能找到原因。我见过有人在第一步就卡住因为他的环境里php -i查到的是一个不存在于 PHP 运行进程里的路径配置改错了地方后面全白费。6. 关于调大上传限制的补充思考把限制调大只是第一步真正上线前还应该考虑后续运维的问题。上传文件大了磁盘空间消耗速度会明显加快尤其是团队频繁交换安装包、视频、设计稿的场景。建议给上传目录配置配额监控或者定期做清理策略。禅道自带文件管理功能可以对历史附件做梳理但大文件是否要保留在本地还是迁移到对象存储也需要根据实际情况决策。另外大文件上传会让 php-fpm 进程长时间被占用每个进程在处理大文件时都会持有较多内存并发上来之后服务器内存可能吃紧。如果团队经常有超过 100M 的附件我更倾向于建议在 Nginx 层直接开启client_body_timeout和超时设置来保护应用层或者在应用层做分块上传和断点续传的改造避免把压力全压在 PHP 上。我在实际部署中还遇到过另一个细节如果你把上传限制改得很大但服务器磁盘分区容量不足用户上传时会发现文件显示上传成功实际写入时因为磁盘满而失败。禅道在这种场景下的报错不一定明确甚至可能只显示“上传失败”而没有具体原因。所以在调大限制的同时也应该检查一下磁盘剩余空间确保上传目录所在分区的容量能满足新需求。至于“到底设成多少合适”我的建议是不要盲目追求大。你需要先统计一下团队日常文件的体积分布。如果基本都是 PDF、Word、Excel三五十兆就够用如果有安装包、日志包、视频演示那可以考虑 200M 到 500M。上限设得越大服务器面临的负载和风险也越高。曾经有位同事为了图省事直接把upload_max_filesize改成 1G结果没过多久测试同事传了一堆视频磁盘直接告警最后又得花时间清理。这种事发生过一次之后我就养成了“按需配置”的习惯绝不再拍脑袋设一个夸张的值。另外如果你的禅道里有好几个项目同时在使用建议在改动之前先和相关同事做一次沟通明确他们最需要的上传文件类型和最大体积避免为了极个别需求把整体限制抬得太高。上线之后也可以定期关注系统日志里的上传记录动态调整数值配置而不是一劳永逸地设置一次就再也不管。7. 用这套思路能复用到哪些场景如果你手上管的不只是禅道还有其它 PHP 应用这套思路完全可以复用。我平时排查“某个 Web 系统上传不了大文件”时永远先按“Nginx —— PHP —— 应用配置”这个顺序来检查而不是一上来就猜是应用系统自身的 bug。举个实际中的例子有一次某内部系统用的是另一个 PHP 开发框架上传文件时永远提示 413。我按这套链路排查发现 Nginx 的client_max_body_size确实被设置为 0不限制了但 PHP 的upload_max_filesize只有 2M并且 php-fpm 还没重启改完重启之后问题立刻消失。再往后这个系统的前端 JS 还有一个手动校验文件大小的逻辑必须同步改掉。这种多层联动的排查思路比死磕某一个配置文件要高效得多。再补充一个冷门场景禅道部署在容器里时修改配置的要点和物理机一致但需要额外注意容器重启后配置文件是否会被镜像覆盖。如果你的php.ini是通过 Dockerfile 写进去的而不是挂载卷持久化的那么每次容器重建都会丢失修改。这种环境里我建议先把配置目录用卷持久化再加一个初始化脚本确保容器启动时自动修改参数避免每次部署都要手工操作一遍。我在实际项目中用过这个方案在启动脚本里加入一行sed命令自动修改php.ini中的上传参数并把client_max_body_size写入 Nginx 配置。这样不管是自动扩容还是手动重启配置都不会丢。这个方法同样适用于非容器环境你可以用部署脚本来代替手动改配置减少人为失误。最后提一句改完权限后如果禅道页面上传还报错记得看服务器端错误日志。我经常会看到有人反复改配置但不去看日志结果问题其实一直是别的原因。/var/log/nginx/error.log和/var/log/php-fpm/www-error.log是最直观的排查入口里面通常直接记录了失败原因比自己在配置里瞎猜快得多。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。