如何通过REST API同时上传XLSX文件与JSON元数据?请求报错排查
解决multipart/form-data上传文件+JSON数据时的InvalidContentTypeException问题
你遇到的这个错误核心原因是客户端代码里文件对象的获取方式错误,再加上服务端处理时没有区分普通表单字段和文件字段,下面一步步给你修复:
1. 客户端代码的关键修复
你的代码里formData.append("file",document.getElementById("fileForm"))这一行出了问题:你传入的是整个表单元素,而不是文件输入框里选中的文件对象。假设你的fileForm是<input type="file" id="fileForm">,那应该获取它的files[0]属性(也就是用户选中的第一个文件)。
另外,transformRequest的写法可以简化,直接在data属性里传入FormData更清晰,同时去掉不必要的enctype配置(jQuery ajax里这不是标准选项)。修改后的客户端代码:
var method = 'POST'; var formData = new FormData(); formData.append("model", JSON.stringify(jsonData)); // 修复文件对象的获取逻辑 formData.append("file", document.getElementById("fileForm").files[0]); $.ajax({ type: method, url : "rest/file/upload", data: formData, // 直接传入FormData对象 processData : false, contentType : false, // 必须设为false,让浏览器自动生成正确的multipart请求头 success: function (data) { console.log("上传成功"); }, error: function (xhr, status, error) { console.error("上传失败:", error); } });
划重点:
contentType: false是避免InvalidContentTypeException的关键,它会让浏览器自动添加正确的multipart/form-data请求头,并自动生成边界标识,手动设置反而容易出错。
2. 服务端代码的优化与修复
你的服务端代码现在会把所有FileItem都当成文件写入临时文件,但model是普通的字符串字段,不需要写入文件。需要判断每个FileItem的类型,分别处理普通字段和文件:
@POST @Path("/upload") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_PLAIN) public Response uploadResumableISOFile(@Context HttpServletRequest request) throws IOException { ServletFileUpload uploader = null; try { DiskFileItemFactory fileFactory = new DiskFileItemFactory(); uploader = new ServletFileUpload(fileFactory); List<FileItem> fileItemsList = uploader.parseRequest(request); Iterator<FileItem> fileItemsIterator = fileItemsList.iterator(); String jsonModel = null; File uploadedFile = null; while (fileItemsIterator.hasNext()) { FileItem fileItem = fileItemsIterator.next(); if (fileItem.isFormField()) { // 处理普通表单字段:解析JSON数据 if ("model".equals(fileItem.getFieldName())) { jsonModel = fileItem.getString(); System.out.println("收到的JSON数据: " + jsonModel); } } else { // 处理文件字段:写入临时文件 uploadedFile = File.createTempFile("TEMP_", ".xlsx"); fileItem.write(uploadedFile); System.out.print("文件 " + fileItem.getName() + " 上传成功,临时文件路径: " + uploadedFile.getAbsolutePath()); } } // 这里可以添加JSON转Java对象的逻辑(示例) // ObjectMapper mapper = new ObjectMapper(); // YourModel model = mapper.readValue(jsonModel, YourModel.class); System.out.println("所有内容上传完成..."); return Response.status(Response.Status.OK).entity("上传成功").build(); } catch (Exception e) { System.err.println("上传失败异常: " + e.getMessage()); e.printStackTrace(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("上传失败: " + e.getMessage()).build(); } }
3. 额外检查点
- 确保你的文件输入框配置正确:
<input type="file" id="fileForm" accept=".xlsx">,并且用户确实选中了文件再提交请求。 - 检查服务端的
commons-fileupload和commons-io依赖版本是否兼容,避免依赖冲突导致的请求解析异常。
内容的提问来源于stack exchange,提问作者Swap
相关产品推荐
相关产品推荐

