Skip to content

Instantly share code, notes, and snippets.

@animatedlew
Last active September 7, 2017 02:25
Show Gist options
  • Save animatedlew/e30e77a6c6e4051fe0695ccdc23c2eb1 to your computer and use it in GitHub Desktop.
Save animatedlew/e30e77a6c6e4051fe0695ccdc23c2eb1 to your computer and use it in GitHub Desktop.
import java.io.File
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.Multipart.BodyPart
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.FileIO
import io.circe._
import concurrent.duration._
import language.postfixOps
import scala.io.StdIn
import de.heikoseeberger.akkahttpcirce._
object Main extends App with Directives {
implicit val system = ActorSystem("file-upload")
implicit val materializer = ActorMaterializer()
import system.dispatcher
import FailFastCirceSupport._
case class FormData(file: Option[File] = None, values: Map[String, String] = Map.empty)
object FormData {
implicit val e: Encoder[FormData] = Encoder.forProduct1("values")(_.values)
implicit val d: Decoder[FormData] = Decoder.forProduct1("values")((o: Map[String, String]) => FormData(None, o))
}
val route =
path("upload") {
entity(as[Multipart.FormData]) { data =>
val values = data.parts.mapAsync(1) {
case b: BodyPart if b.name == "file" =>
val file = File.createTempFile("upload", "tmp")
b.entity.dataBytes.runWith(FileIO.toPath(file.toPath)).map(_ => b.name -> file)
case b: BodyPart =>
b.toStrict(2 seconds).map(strict => b.name -> strict.entity.data.utf8String)
}.runFold(FormData())((data, tuple) => {
tuple match {
case ("file", f: File) => data.copy(file = Some(f), values = data.values + ("location" -> f.getAbsolutePath))
case (k, v: String) => data.copy(values = data.values.updated(k, v))
case _ => data
}
})
onSuccess(values)(o => complete(o))
}
}
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
println("Press enter to terminate...")
StdIn.readLine()
bindingFuture.flatMap(_.unbind()).onComplete(_ => system.terminate())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment