Angular13/TypeScript:替代form.submit()遇CORS错误的解决方案咨询
Angular 13+ TypeScript中FormData提交触发CORS问题的解决方案
问题说明
在Angular 13+ TypeScript项目的服务中,尝试用FormData替代传统隐藏表单的form.submit()提交数据时,所有替代方案均触发CORS错误,但原隐藏表单提交方式可正常运行。
可正常运行的隐藏表单提交代码
const form = document.createElement('form'); form.setAttribute('method', 'post'); form.setAttribute('action', theUrl); for (const key in params) { if (params.hasOwnProperty(key) && params[key]) { const hiddenField = document.createElement('input'); hiddenField.setAttribute('type', 'hidden'); hiddenField.setAttribute('name', key); hiddenField.setAttribute('value', params[key]); form.appendChild(hiddenField); } } document.body.appendChild(form); form.submit();
失败的两种实现及错误详情
第一种失败实现(HttpClient + FormData)
var formData: any = new FormData(); for (const key in params) { if (params.hasOwnProperty(key) && params[key]) { formData.append(key, params[key]); } } let clientHeaders = new HttpHeaders({ 'Content-Type': 'multipart/form-data', 'Type': 'formData', 'Access-Control-Allow-Origin': '*' }); return this.httpClient.post(theUrl, formData, { headers: clientHeaders }) .pipe(tap( (response) => { console.log(response); }, () => { console.error(Error); }); ) )
第二种失败实现(fetch + URLSearchParams)
var formData: any = new FormData(); for (const key in params) { if (params.hasOwnProperty(key) && params[key]) { formData.append(key, params[key]); } } const data = new URLSearchParams(formData); return fetch(theUrl, { method: 'post', body: data, mode: 'cors' });
Chrome中CORS错误详情
A cross-origin resource sharing (CORS) request was blocked because of invalid or missing response headers of the request or the associated preflight request . To fix this issue, ensure the response to the CORS request and/or the associated preflight request are not missing headers and use valid header values. Note that if an opaque response is sufficient, the request's mode can be set to no-cors to fetch the resource with CORS disabled; that way CORS headers are not required but the response content is inaccessible (opaque). 1 request Request Status Preflight Request (if problematic) Header Problem Invalid Value (if available) redirect blocked Access-Control-Allow-Origin Missing Header
替代解决方案(除隐藏表单外)
方案1:使用no-cors模式提交(无需处理响应时)
如果不需要读取响应内容,仅需完成数据提交,可以将fetch的模式设置为no-cors,浏览器会跳过CORS检查,但响应内容会变为不可访问的opaque类型。
const formData = new FormData(); for (const key in params) { if (params.hasOwnProperty(key) && params[key]) { formData.append(key, params[key]); } } return fetch(theUrl, { method: 'post', body: formData, mode: 'no-cors' });
方案2:模拟表单的application/x-www-form-urlencoded格式提交
原隐藏表单提交的是application/x-www-form-urlencoded格式,属于浏览器认定的简单请求,不会触发OPTIONS预检。可直接用URLSearchParams构建参数,且不要手动设置Content-Type,让HttpClient自动处理:
const formParams = new URLSearchParams(); for (const key in params) { if (params.hasOwnProperty(key) && params[key]) { formParams.append(key, params[key]); } } return this.httpClient.post(theUrl, formParams) .pipe( tap(response => console.log(response)), catchError(error => { console.error(error); return throwError(() => error); }) );
关键说明:
- 手动设置
Content-Type: multipart/form-data会触发预检请求,且容易因缺少boundary导致格式错误; Access-Control-Allow-Origin是后端响应头,前端设置该请求头无效,反而可能触发预检。
方案3:使用JSONP(限GET请求,需后端支持)
如果后端支持JSONP,可以通过Angular的HttpClientJsonpModule绕过CORS限制,但该方式仅适用于GET请求,若需提交数据需后端允许通过GET参数传递。
内容的提问来源于stack exchange,提问作者Pandele Florin
相关产品推荐
相关产品推荐

