跨域上传必须配置 xhrFields: { withCredentials: true },否则 Cookie 和认证头无法发送;后端需精确设置 CORS 响应头,禁止使用 Access-Control-Allow-Origin: *,且 Content-Type 不可手动覆盖。

layui upload 跨域上传必须配 xhrFields: { withCredentials: true }
跨域上传带 Cookie 或自定义认证头时,xhrFields 是唯一生效位置。Layui upload.render 不读取 $.ajaxSetup,也不响应 beforeSend,硬写 headers: { Authorization: '...' } 但漏掉 xhrFields,浏览器根本不会发凭证。
常见错误现象:
- 控制台报
No 'Access-Control-Allow-Origin' header,但后端明明配了Access-Control-Allow-Origin: * - 后端收不到 Cookie,
document.cookie有值,请求却没发过去 - 带
Authorization头的上传被拦截,预检(OPTIONS)返回 403
正确写法示例:
layui.upload.render({
elem: '#upload',
url: 'https://api.example.com/upload',
xhrFields: { withCredentials: true },
headers: { 'X-Request-ID': 'abc123' },
before: function(obj) {
this.headers.Authorization = 'Bearer ' + localStorage.getItem('token');
}
});
后端 CORS 响应头必须精确匹配前端配置
前端开了 withCredentials: true,后端就不能用通配符 Access-Control-Allow-Origin: *,必须指定具体域名,比如 https://myapp.com;否则浏览器直接拦截。
还需同步配置以下响应头:
-
Access-Control-Allow-Credentials: true(必需,且值必须是字符串"true",不能是布尔值) -
Access-Control-Allow-Headers必须显式列出你用到的头,例如Authorization, X-Request-ID -
Access-Control-Expose-Headers如果前端要读响应头(如X-Upload-ID),得在这里声明
如果后端用的是 Nginx,典型配置片段:
add_header 'Access-Control-Allow-Origin' 'https://myapp.com'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Headers' 'Authorization, X-Request-ID'; add_header 'Access-Control-Expose-Headers' 'X-Upload-ID';
跨域上传时 Content-Type 不能手动覆盖
文件上传必须走 multipart/form-data,这是浏览器自动设置的边界和编码格式。如果你在 headers 里硬写 'Content-Type': 'application/json',后端收不到完整文件,甚至直接 400 报错。
Layui upload 会自动处理 Content-Type,你只需要确保:
- 不要在
headers里设Content-Type - 业务参数(如
userId、folderId)统一走data配置项,而不是塞进 headers - 如果后端要求
X-Requested-With,可以加,但别碰Content-Type和Accept
换域名上传时,xhrFields 和 headers 都要重置
动态切换上传地址(比如测试环境切生产环境)时,仅改 url 不够。如果新域名也需要带 Cookie 或 token,xhrFields 和 headers 必须随 URL 一起更新——它们不会自动继承或缓存。
推荐做法是:封装一个工厂函数,每次调用 upload.render 前重新生成配置对象,避免复用旧实例的引用。
容易被忽略的点:
- 同一页面多次调用
upload.render,旧实例未销毁,可能造成事件重复绑定或 headers 混乱 - token 过期后,
before回调里取localStorage.getItem('token')返回 null,但没做中断,导致 401 请求发出去再失败 - IE10+ 才支持
withCredentials,低版本需降级为服务端代理或表单提交


















