Angular通过POST请求上传CSV至Spring应用的实现及报错解决
报错根因
你当前代码触发后端返回Content type 'application/json' not supported,核心是两个逻辑错误:
- 完全混淆了Angular
HttpClient.post()的参数结构。post方法的固定入参顺序为post(请求URL, 实际请求负载, 可选配置项)。你现在把params查询参数、formData文件实例全部当作普通请求体,塞到了第二个参数的位置,最终Angular会把这个普通JS对象默认序列化为application/json格式发送,和后端期望的文件上传格式完全不匹配。 - 没有适配FormData格式的请求头处理逻辑,导致默认的json请求头覆盖了正确的文件上传头信息。
修正后(Multipart文件上传场景,适配绝大多数Spring接收MultipartFile的接口)
@ViewChild('fileImportInput') fileImportInput: any; fileChangeListener($event: any): void { const files = $event.srcElement.files; if (!files?.length) return; const studentsFile = files[0]; const formData = new FormData(); // 这里的第一个参数值必须和Spring后端@RequestPart/@RequestParam里写的文件参数名完全一致 formData.append('studentsFile', studentsFile, studentsFile.name); this.http.post('/api/enroll', formData, { // 批量ID作为URL查询参数携带,放到第三参的params配置里 params: { batchId: this.batchId }, // 关闭Angular默认的json格式请求头覆盖,让浏览器自动生成带boundary的正确multipart头 headers: { 'Content-Type': null } }).subscribe(response => { console.log(response); }); }
关键注意事项
- 绝对不要手动硬写
Content-Type: multipart/form-data:这个请求头必须携带浏览器自动生成的随机边界分隔符,手动写死会导致后端无法正确拆分文件内容。将值设为null是为了告知Angular不要篡改浏览器自动生成的头信息,兼容所有低版本Angular的FormData上传逻辑。 - FormData的参数名要和后端对齐:
append方法的第一个字符串参数(当前代码里的'studentsFile'),必须和Spring接口接收文件时的注解参数名完全一致,否则后端会找不到上传的文件。 - 查询参数无需手动转字符串:HttpClient会自动将
params对象的字段序列化为URL查询参数,直接传batchId的原始值即可,不需要额外套字符串模板。
纯CSV原样上传场景(如果后端接口是直接接收原始CSV文本流,不做Multipart封装)
如果你的后端没有用MultipartFile封装文件,而是直接读取请求体的原始CSV流,不需要构造FormData,直接传文件对象即可:
fileChangeListener($event: any): void { const files = $event.srcElement.files; if (!files?.length) return; const studentsFile = files[0]; this.http.post('/api/enroll', studentsFile, { params: { batchId: this.batchId }, headers: { 'Content-Type': 'text/csv' } }).subscribe(response => { console.log(response); }); }
内容的提问来源于stack exchange,提问作者Kishan Mishra
相关产品推荐
相关产品推荐

