Upload组件上传大文件时总是失败,怎么解决?

公孙彬丽 阅读 35

我用的是 Ant Design 的 Upload 组件,上传小于 10MB 的文件没问题,但一传 50MB 以上的视频就直接报错,控制台显示 net::ERR_CONNECTION_RESET。后端同事说服务器配置没问题,Nginx 的 client_max_body_size 也调大了。

我试过在 beforeUpload 里加 loading 提示,也设置了 fileList 的状态管理,但问题还是出在网络请求上。是不是前端还需要额外配置什么?比如分片上传或者调整超时时间?

const props = {
  name: 'file',
  action: '/api/upload',
  headers: {
    authorization: 'Bearer ' + token,
  },
  onChange(info) {
    if (info.file.status === 'done') {
      message.success('上传成功');
    } else if (info.file.status === 'error') {
      message.error('上传失败');
    }
  },
};
我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
Des.永莲
这个问题我之前也遇到过,说白了就是请求超时或者被拦截了。Nginx 那边的 client_max_body_size 调大了不假,但还有个东西很容易忽略——Nginx 的 proxy_read_timeout 和 proxy_connect_timeout 默认都很小,大文件上传根本撑不住。

不过先说前端的解决办法,Ant Design 的 Upload 组件本身没有直接暴露 timeout 参数,你得用 customRequest 自己写请求:

const props = {
name: 'file',
action: '/api/upload',
customRequest: (options) => {
const { action, file, headers, onProgress, onSuccess, onError } = options;

const formData = new FormData();
formData.append('file', file);

const xhr = new XMLHttpRequest();
xhr.open('POST', action);
xhr.setRequestHeader('Authorization', 'Bearer ' + token);

// 设置超时时间,单位是毫秒,5分钟够用了
xhr.timeout = 300000;

xhr.upload.onprogress = (e) => {
onProgress({ percent: (e.loaded / e.total) * 100 });
};

xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
onSuccess(xhr.response);
} else {
onError(new Error('上传失败'));
}
};

xhr.onerror = () => {
onError(new Error('网络错误'));
};

// 超时处理
xhr.ontimeout = () => {
onError(new Error('请求超时'));
};

xhr.send(formData);

return {
abort: () => xhr.abort()
};
},
onChange(info) {
if (info.file.status === 'done') {
message.success('上传成功');
} else if (info.file.status === 'error') {
message.error('上传失败');
}
},
};


先加上 timeout 试试能不能跑通。

如果还是不行,那大概率是 Nginx 那边的超时配置没跟上。你让后端同事看一下这几个参数:

nginx.conf 里需要调整 proxy_read_timeout、proxy_send_timeout、proxy_connect_timeout,最好都设成 300s 以上。另外 client_max_body_size 这个你已经调过了。

还有一种情况是后端框架本身对请求体大小有限制,比如 Spring Boot 的 server.tomcat.max-http-post-size,或者 Express 的 body-parser limit,这个也得让后端确认一下。

如果文件经常是几百兆那种级别,那就得考虑分片上传了,可以看看 vue-multipart 或者直接搜"大文件分片上传"的方案,那种改动比较大,先把上面这些排查完再说。
点赞
2026-03-19 04:08
ლ子骞
ლ子骞 Lv1
ERR_CONNECTION_RESET 基本就是连接断了,大概率是超时。后端同事说 Nginx 没问题,让他再查查 proxy_read_timeout 或者后端服务(比如 PHP-FPM 或 Node)的超时配置,光改包体大小没用。

前端这边先把超时时间拉长。Ant Design 的 Upload 默认没暴露 timeout 配置,得用 customRequest 自己封装一个请求。

直接用这个:

import { Upload, message, Progress } from 'antd';
import axios from 'axios';

const customRequest = async (options) => {
const { file, onProgress, onSuccess, onError } = options;
const formData = new FormData();
formData.append('file', file);

try {
// 关键点:设置超时时间,这里设为 0 表示永不超时,或者设个 10 分钟
const res = await axios.post('/api/upload', formData, {
timeout: 10 * 60 * 1000,
onUploadProgress: (event) => {
// 别忘了把进度回传给 Upload 组件,否则进度条不动
const percent = Math.floor((event.loaded / event.total) * 100);
onProgress({ percent }, file);
},
});
onSuccess(res.data, file);
} catch (err) {
onError(err);
}
};

const props = {
name: 'file',
customRequest: customRequest, // 覆盖默认上传逻辑
onChange(info) {
if (info.file.status === 'done') {
message.success('上传成功');
} else if (info.file.status === 'error') {
message.error('上传失败');
}
},
};

// 渲染部分




如果文件特别大,比如几百兆甚至上 G,光改超时容易翻车,必须上分片上传。思路是把文件切片,并发上传,最后后端合并。简单的切片逻辑给你贴一份,前提是后端得配合写个合并接口:

const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB 一个切片

const uploadByChunks = async (file) => {
const totalChunks = Math.ceil(file.size / CHUNK_SIZE);

for (let i = 0; i < totalChunks; i++) {
const start = i * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, file.size);
const chunk = file.slice(start, end);

const formData = new FormData();
formData.append('file', chunk);
formData.append('name', file.name);
formData.append('index', i);
formData.append('total', totalChunks);

await axios.post('/api/upload-chunk', formData);
}

// 通知后端合并
await axios.post('/api/merge', { name: file.name, total: totalChunks });
};


先试试改超时那个,50MB 一般就能过了。
点赞 1
2026-03-02 23:15