任意类型文件无限制上传至服务器的代码实现与NGINX配置
任意类型无大小限制文件上传实现方案(Nginx+HTML+JS+PHP)
一、Nginx上传限制配置调整
Nginx默认自带上传大小限制,核心控制参数是client_max_body_size,默认值为1MB,超过阈值的请求会直接返回413状态码。要关闭大小限制按以下步骤操作:
- 定位Nginx配置文件,全局配置一般在
/etc/nginx/nginx.conf,站点单独配置通常在/etc/nginx/conf.d/或/etc/nginx/sites-available/目录下对应域名的conf文件中。 - 在
http块(全局生效)、server块(单站点生效)或对应上传接口的location块(单接口生效)中添加以下配置,配置优先级为location > server > http:
# 设为0即为完全禁用上传大小检查,如需设置阈值可写为10240m(对应10GB)这类值 client_max_body_size 0; # 大文件传输需要调大超时时间,避免传输中途连接断开 client_body_timeout 300s; send_timeout 300s; # 如果Nginx做反向代理转发请求到后端服务,需要额外加这行 proxy_read_timeout 300s; # 确认请求体临时存储路径有Nginx运行用户的写入权限,避免大文件临时写入失败 client_body_temp_path /var/nginx/client_body_temp;
- 先执行
nginx -t检查配置语法是否正确,确认无误后执行nginx -s reload重载配置生效。
注意:公网生产环境不建议完全关闭上传大小限制,无鉴权的无限制上传很容易被恶意攻击者传大文件占满服务器磁盘,直接导致服务不可用,建议根据业务需求设置合理阈值,必须开无限制的话一定要做好接口鉴权和磁盘配额监控
二、前端代码实现(HTML+JavaScript)
前端通过FormData传递文件,用XMLHttpRequest实现上传进度监听,基础可运行代码如下:
<!-- 上传区域 --> <input type="file" id="filePicker" accept="*"> <button id="startUpload">上传文件</button> <div style="width: 500px;height: 20px;border: 1px solid #eee;margin: 10px 0;"> <div id="progress" style="width: 0%;height: 100%;background: #2385bb;"></div> </div> <p id="statusTip"></p>
const filePicker = document.getElementById('filePicker'); const startUpload = document.getElementById('startUpload'); const progress = document.getElementById('progress'); const statusTip = document.getElementById('statusTip'); startUpload.addEventListener('click', () => { const file = filePicker.files[0]; if (!file) { statusTip.textContent = '请先选择要上传的文件'; return; } const formData = new FormData(); formData.append('targetFile', file); formData.append('originName', file.name); const xhr = new XMLHttpRequest(); // 监听上传进度 xhr.upload.onprogress = (e) => { if (e.lengthComputable) { const percent = ((e.loaded / e.total) * 100).toFixed(1); progress.style.width = `${percent}%`; statusTip.textContent = `上传中:${percent}%`; } }; // 上传完成回调 xhr.onload = () => { if (xhr.status === 200) { const res = JSON.parse(xhr.responseText); statusTip.textContent = res.msg; } else { statusTip.textContent = `上传失败,状态码:${xhr.status}`; } }; // 上传错误回调 xhr.onerror = () => { statusTip.textContent = '网络异常,上传失败'; }; xhr.open('POST', './upload.php'); xhr.send(formData); });
单文件大小超过10G的场景,建议加分片上传逻辑:把文件按固定大小(比如10MB/片)切割,带分片序号逐片上传,后端接收完全部分片后按序号合并成完整文件,能避免网络波动导致整文件重传,同时降低服务端内存占用。
三、后端PHP实现
PHP本身也有默认上传大小限制,只改Nginx配置不调整PHP配置的话,大文件上传依然会失败,先调整php.ini配置:
- 找到对应运行模式的php.ini文件,php-fpm模式下配置路径一般为
/etc/php/{版本号}/fpm/php.ini,修改以下参数:
; POST请求最大大小限制,设为0为不限制 post_max_size = 0 ; 单上传文件最大大小限制,设为0为不限制 upload_max_filesize = 0 ; 内存限制,大文件上传场景建议设为-1(不限制),避免内存不足报错 memory_limit = -1 ; 脚本最大执行时间、输入时间设为0(不限制),避免大文件传输过程中脚本超时退出 max_execution_time = 0 max_input_time = 0
- 重启php-fpm服务生效,比如PHP8.1版本执行
systemctl restart php8.1-fpm即可。 - 新建upload.php处理上传请求,代码如下:
<?php header('Content-Type: application/json;charset=utf-8'); // 提前创建uploads目录,给Nginx和PHP运行用户分配该目录的读写权限 $savePath = __DIR__ . '/uploads/'; if (!is_dir($savePath)) { mkdir($savePath, 0755, true); } if (!isset($_FILES['targetFile'])) { echo json_encode(['code' => 1, 'msg' => '未接收到上传文件']); exit; } $uploadFile = $_FILES['targetFile']; $fileName = $_POST['originName'] ?? $uploadFile['name']; // 过滤文件名非法字符,防范路径遍历漏洞 $fileName = preg_replace('/[^\w\.\-\x{4e00}-\x{9fa5}]/u', '', $fileName); $targetFile = $savePath . $fileName; // 处理上传错误 if ($uploadFile['error'] !== UPLOAD_ERR_OK) { $errorMap = [ UPLOAD_ERR_INI_SIZE => '文件大小超过php.ini配置限制', UPLOAD_ERR_FORM_SIZE => '文件大小超过表单限制', UPLOAD_ERR_PARTIAL => '文件传输不完整', UPLOAD_ERR_NO_TMP_DIR => '服务端临时目录不存在', UPLOAD_ERR_CANT_WRITE => '文件写入磁盘失败' ]; echo json_encode(['code' => 1, 'msg' => $errorMap[$uploadFile['error']] ?? '未知上传错误']); exit; } if (move_uploaded_file($uploadFile['tmp_name'], $targetFile)) { echo json_encode(['code' => 0, 'msg' => "文件上传成功,保存路径:{$targetFile}"]); } else { echo json_encode(['code' => 1, 'msg' => '文件保存失败,请检查目录权限']); } ?>
四、落地注意事项
- 无限制上传风险极高:公网环境下必须给上传接口加鉴权(比如登录态校验、签名校验),禁止匿名上传,同时给上传目录设置磁盘配额,避免磁盘被写满导致服务宕机。
- 所有配置修改后必须重载/重启对应服务才会生效,建议先用小文件验证全流程正常,再测试大文件上传。
- 超过2G的文件上传,建议优先选择分片+断点续传方案,稳定性远高于整文件上传。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

