You need to enable JavaScript to run this app. Play Framework使用multipartFormData上传文件后如何返回仓库层JSON响应
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 19:27:00