Play Framework - Respond with JSON after uploading a file (multipartFormData)

164 views Asked by At

I am using this code to upload an image on server , that i get from this link play upload

 def upload = Action(parse.multipartFormData) { request =>
    request.body
      .file("picture")
      .map { picture =>
        val dataParts = request.body.dataParts;

        val filename = Paths.get(picture.filename).getFileName
        val fileSize = picture.fileSize
        val contentType = picture.contentType

         val picturePaths =
           picture.ref.copyTo(
             Paths.get(
               s"/opt/docker/images/$filename"
             ),
             replace = true
           )
        if (dataParts.get("firstPoint") == None) {
          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))
          }
        }
        Ok(s"picturePaths ${picturePaths}")

      }
      .getOrElse(Ok("Invalid Format"))
  }

This code works very well, but on the response I want to get the response from the repository. How can i await for the response of the repository to return this?

Can you give me any idea how can i do it? Thanks in advance.

1

There are 1 answers

0
Gaël J On BEST ANSWER

If we simplify your code to the essential bits, you have:

def upload = Action(parse.multipartFormData) { request =>
    request.body
      .file("picture")
      .map { picture =>
        if (someConditionA) {
          someBusinessLogicA().map { data =>
            Created(Json.toJson(data._2))
          }
        } else {
          someBusinessLogicB().map { data =>
            Created(Json.toJson(data._2))
          }
        }
        Ok(s"picturePaths ${picturePaths}")
      }
      .getOrElse(Ok("Invalid Format"))
}

There are 2 problems:

  • the return of your if/else is swallowed by the Ok(s"picturePaths ${picturePaths}")
  • assuming your business logic returns Future[_] you need to "propagate" the Future everywhere

Something like this should work:

def upload = Action.async(parse.multipartFormData) { request =>
    request.body
      .file("picture")
      .map { picture =>
        if (someConditionA) {
          someBusinessLogicA().map { data =>
            Created(Json.toJson(data._2))
          }
        } else {
          someBusinessLogicB().map { data =>
            Created(Json.toJson(data._2))
          }
        }
      }
      .getOrElse(Future.successful(Ok("Invalid Format")))
}

Notice the Action.async and the Future in the getOrElse.