You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅为NGINX特定路径/URL覆盖client_max_body_size限制?

Nginx全局client_max_body_size限制与特定端点例外配置问题

我们希望将服务器全局的client_max_body_size设置为较低值(如50M)以降低攻击风险,但为需要大文件上传的特定端点/uploadtest/index.php设置更大的限制(如500M)。

我们尝试了如下两种配置:

第一种配置

全局设置client_max_body_size为50M,在location = /uploadtest/index.php中设置为500M,但上传时始终收到“Entity too large”错误。
(注:php.ini和php-fpm.conf中的配置未对此进行限制,提升全局限制后可正常上传文件。)

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    keepalive_timeout   1200;
    types_hash_max_size 4096;
    proxy_connect_timeout       1200;
    proxy_send_timeout          1200;
    proxy_read_timeout          1200;
    send_timeout                1200;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;
        client_max_body_size    50M;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location = /uploadtest/index.php {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param HTTPS off;
            fastcgi_pass unix:/run/php-fpm/www.sock;
            fastcgi_read_timeout 1200;
            http2_push_preload on;
            fastcgi_buffers 16 128k;
            fastcgi_buffer_size 256k;
            fastcgi_busy_buffers_size 256k;
            client_max_body_size    500M;
        }

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param HTTPS off;
            fastcgi_pass unix:/run/php-fpm/www.sock;
            fastcgi_read_timeout 1200;
            http2_push_preload on;
            fastcgi_buffers 16 128k;
            fastcgi_buffer_size 256k;
            fastcgi_busy_buffers_size 256k;
        }        
    }
}

第二种配置

全局设置client_max_body_size为500M,其他路径设置为50M,但无法限制其他上传路径,所有路径均开放为500M的限制。

server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;
        client_max_body_size    500M;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location = /uploadtest/index.php {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param HTTPS off;
            fastcgi_pass unix:/run/php-fpm/www.sock;
            fastcgi_read_timeout 1200;
            http2_push_preload on;
            fastcgi_buffers 16 128k;
            fastcgi_buffer_size 256k;
            fastcgi_busy_buffers_size 256k;
            client_max_body_size    500M;
        }

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            client_max_body_size  50M;
            fastcgi_param HTTPS off;
            fastcgi_pass unix:/run/php-fpm/www.sock;
            fastcgi_read_timeout 1200;
            http2_push_preload on;
            fastcgi_buffers 16 128k;
            fastcgi_buffer_size 256k;
            fastcgi_busy_buffers_size 256k;
        }

        location / {
            try_files $uri $uri/ /index.php?$args;
            client_max_body_size 50M;
        }
    }

问题

请问是否可以通过这种方式限制全局上传限制?如果可以,当前配置遗漏了什么?


解决方案

可以通过这种方式实现全局限制+特定端点例外的需求,问题出在Nginx的client_max_body_size检查时机和location匹配优先级上:

第一种配置的问题分析与修复

Nginx会在请求进入server块时就检查client_max_body_size,而非等到匹配到具体location之后。因此即使你在location = /uploadtest/index.php中设置了更大的值,全局的50M限制已经先触发了错误。

修复方法是将全局默认的client_max_body_size移到location /块中,同时保留特定端点的500M设置。这样只有当请求匹配不到更高优先级的location时,才会应用50M的限制。修改后的server块配置如下:

server {
    listen       80;
    listen       [::]:80;
    server_name  _;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
        try_files $uri $uri/ /index.php?$args;
        client_max_body_size    50M; # 全局默认限制放在这里
    }

    location = /uploadtest/index.php {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_param HTTPS off;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_read_timeout 1200;
        http2_push_preload on;
        fastcgi_buffers 16 128k;
        fastcgi_buffer_size 256k;
        fastcgi_busy_buffers_size 256k;
        client_max_body_size    500M; # 特定端点的更大限制
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_param HTTPS off;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_read_timeout 1200;
        http2_push_preload on;
        fastcgi_buffers 16 128k;
        fastcgi_buffer_size 256k;
        fastcgi_busy_buffers_size 256k;
        client_max_body_size    50M; # 其他PHP路径应用默认限制
    }        
}

第二种配置的问题分析

第二种配置中,server块设置的500M优先级高于location块中的50M。因为client_max_body_size的生效逻辑是取请求过程中最大的配置值,server级的500M会覆盖所有location里的50M设置,导致所有路径都开放为500M。

关键原理补充

  • client_max_body_size的检查在请求头读取完成后立即执行,此时Nginx可能还未完成location匹配,因此server级配置会先生效。
  • 精确匹配的location = /path优先级高于正则匹配的location ~ \.php$,所以特定端点的配置会被优先匹配。

内容的提问来源于stack exchange,提问作者Denny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:29:59