JS前端上传JSON文件至Scala ZHttp后端:提取纯JSON内容
问题根源
当你用FormData构造请求时,哪怕手动设置Content-Type为application/json,浏览器依然会自动将请求头改为multipart/form-data并添加WebKitFormBoundary边界标识——因为FormData本身就是为多部分表单数据设计的。后端收到的是完整的multipart格式请求体,不是纯JSON字符串,直接用JSON解析器读取自然会报错。
解决方案
根据你的实际需求,有两种处理方式:
方案1:直接提交JSON数据(无需上传文件)
如果你的需求只是传递{"name": "John", "age": 35}这段JSON内容,完全没必要用FormData,直接发送JSON字符串即可:
const jsonData = {"name": "John", "age": 35}; fetch('/your-api-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(jsonData), }) .then(res => res.json()) .catch(err => console.error('请求失败:', err));
这种方式后端能直接解析纯JSON体,你之前测试过这种情况是正常的,适合仅提交JSON数据的场景。
方案2:后端解析Multipart请求(确实需要上传JSON文件)
如果你的需求是让用户上传本地JSON文件,那前端用FormData是正确的,但后端需要处理multipart/form-data类型的请求,先提取文件内容再解析JSON。
在Scala zhttp中可以这样实现:
import zhttp.http._ import zhttp.service.Server import zio._ import io.circe.parser object JsonFileUploadServer extends ZIOAppDefault { val uploadApp: HttpApp[Any, Throwable] = Http.collectZIO[Request] { case req@Method.POST -> !! / "upload-json-file" => req.multipart.flatMap { multipart => // 匹配前端FormData中设置的文件字段名,这里假设是"jsonFile" multipart.files.find(_.name == "jsonFile") match { case Some(file) => // 读取文件内容为字符串,再解析JSON file.content.asString.flatMap { fileContent => parser.parse(fileContent) .fold( parseErr => ZIO.succeed(Response.text(s"JSON解析失败: ${parseErr.getMessage}").setStatus(Status.BadRequest)), json => ZIO.succeed(Response.json(json.toString())) ) } case None => ZIO.succeed(Response.text("未找到名为jsonFile的上传文件").setStatus(Status.BadRequest)) } } } override val run = Server.start(8080, uploadApp) }
对应的前端上传代码(无需手动设置Content-Type):
// 假设页面中有<input type="file" id="jsonFileInput" accept=".json"> const fileInput = document.getElementById('jsonFileInput'); const formData = new FormData(); formData.append('jsonFile', fileInput.files[0]); fetch('/upload-json-file', { method: 'POST', body: formData, // 浏览器会自动添加正确的multipart请求头 }) .then(res => res.text()) .catch(err => console.error('上传失败:', err));
内容的提问来源于stack exchange,提问作者Aleksey N Yakushev
相关产品推荐
相关产品推荐

