Play Framework使用multipartFormData上传文件后如何返回仓库层JSON响应
问题根因
你当前的代码存在两个核心问题导致无法返回repository的操作结果:
- 你使用的是同步Action定义,而
point_LocationRepository.create方法返回的是Future类型的异步结果,你没有等待这个异步操作执行完成,就直接在逻辑末尾返回了固定的路径结果,相当于异步的存储逻辑还没执行完,接口就已经返回响应了 - 整个逻辑的返回值类型不统一,
map块里两个分支返回的是Future[Result],但你额外加了一行返回Result类型的路径响应,类型不匹配也会导致异步结果不生效
修正后代码
import scala.concurrent.Future // 确认你已经引入了Future相关依赖 def upload = Action.async(parse.multipartFormData) { request => request.body .file("picture") .map { picture => val dataParts = request.body.dataParts val filename = Paths.get(picture.filename).getFileName val picturePaths = picture.ref.copyTo( Paths.get(s"/opt/docker/images/$filename"), replace = true ) // 直接返回两个分支的Future结果,删除原来多余的路径返回语句 if (dataParts.get("firstPoint").isEmpty) { val pointlocation = new Point_LocationModel( dataParts.get("step").get(0), dataParts.get("backgroundTargetName").get(0), dataParts.get("x").get(0), dataParts.get("y").get(0), dataParts.get("z").get(0), dataParts.get("rotation").get(0), dataParts.get("note").get(0), dataParts.get("tag").get(0), dataParts.get("work_session_id").get(0), picturePaths.toString ) point_LocationRepository.create(pointlocation).map { data => Created(Json.toJson(data._2)) } } else { val jValuefirstPoint = Json.parse(dataParts.get("firstPoint").get(0)).as[PointModel] val jValuesecondPoint = Json.parse(dataParts.get("secondPoint").get(0)).as[PointModel] val pointlocation = new Point_LocationModel( dataParts.get("step").get(0), dataParts.get("backgroundTargetName").get(0), Some(jValuefirstPoint), Some(jValuesecondPoint), dataParts.get("rotation").get(0), dataParts.get("note").get(0), dataParts.get("tag").get(0), dataParts.get("work_session_id").get(0), picturePaths.toString ) point_LocationRepository.create(pointlocation).map { data => logger.info(s"repoResponse: ${data}") Created(Json.toJson(data._2)) } } } // 把getOrElse的返回值包成Future.successful,和前面的Future类型统一 .getOrElse(Future.successful(Ok("Invalid Format"))) }
核心改动说明
- 把原来的同步
Action改成Action.async,明确告诉Play这个接口返回的是异步结果,Play会自动等待Future执行完成后再返回响应,不需要你手动阻塞等待,不会影响线程池性能 - 删掉了逻辑末尾多余的
Ok(s"picturePaths ${picturePaths}")返回语句,直接把两个分支中repository操作返回的Future作为整个map块的返回值 - 把
getOrElse里的固定返回包在Future.successful里,让整个方法的返回值统一为Future[Result],符合Action.async的类型要求
可选优化:你当前直接用.get(0)取dataParts的字段值,如果请求缺失对应参数会直接抛出异常,建议补充参数校验逻辑,用getOrElse处理缺省场景或者返回参数错误的提示响应
内容的提问来源于stack exchange,提问作者Edit Axha
相关产品推荐
相关产品推荐

