如何运行akka示例代码“以流方式使用主机级API”?

时间:2017-09-18 08:08:50

标签: scala akka

当我在这个网站链接尝试akka的示例代码时 http://doc.akka.io/docs/akka-http/current/scala/http/client-side/host-level.html#using-the-host-level-api-in-a-streaming-fashion,我遇到了 filesToUpload 功能没有实现的问题。例外情况报告如下:

"C:\Program Files (x86)\Java\jdk1.8.0_45\bin\java" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2017.2.2\lib\idea_rt.jar=64568:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2017.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\charsets.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\deploy.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\access-bridge-32.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\cldrdata.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\dnsns.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\jaccess.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\jfxrt.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\localedata.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\nashorn.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\sunec.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\sunjce_provider.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\sunmscapi.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\sunpkcs11.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\ext\zipfs.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\javaws.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\jce.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\jfr.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\jfxswt.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\jsse.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\management-agent.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\plugin.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\resources.jar;C:\Program Files (x86)\Java\jdk1.8.0_45\jre\lib\rt.jar;E:\workspaces\akka\akka-quickstart-scala-project1\akka-quickstart-scala\target\scala-2.11\classes;C:\Users\xiaofengwo\.ivy2\cache\org.scala-lang.modules\scala-java8-compat_2.11\bundles\scala-java8-compat_2.11-0.7.0.jar;C:\Users\xiaofengwo\.ivy2\cache\org.scala-lang\scala-library\jars\scala-library-2.11.8.jar;C:\Users\xiaofengwo\.ivy2\cache\com.typesafe\config\bundles\config-1.3.0.jar;C:\Users\xiaofengwo\.ivy2\cache\com.typesafe\ssl-config-core_2.11\bundles\ssl-config-core_2.11-0.2.1.jar;C:\Users\xiaofengwo\.ivy2\cache\com.typesafe.akka\akka-actor_2.11\jars\akka-actor_2.11-2.4.16.jar;C:\Users\xiaofengwo\.ivy2\cache\com.typesafe.akka\akka-http-core_2.11\jars\akka-http-core_2.11-10.0.3.jar;C:\Users\xiaofengwo\.ivy2\cache\com.typesafe.akka\akka-http_2.11\jars\akka-http_2.11-10.0.3.jar;C:\Users\xiaofengwo\.ivy2\cache\com.typesafe.akka\akka-parsing_2.11\jars\akka-parsing_2.11-10.0.3.jar;C:\Users\xiaofengwo\.ivy2\cache\com.typesafe.akka\akka-stream_2.11\jars\akka-stream_2.11-2.4.16.jar;C:\Users\xiaofengwo\.ivy2\cache\org.reactivestreams\reactive-streams\jars\reactive-streams-1.0.0.jar;C:\Users\xiaofengwo\.ivy2\cache\org.scala-lang.modules\scala-parser-combinators_2.11\bundles\scala-parser-combinators_2.11-1.0.4.jar" com.lightbend.akka.sample.FileUploadTest
Exception in thread "main" scala.NotImplementedError: an implementation is missing
    at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
    at com.lightbend.akka.sample.FileUploadTest$.filesToUpload(FileUploadTest.scala:25)
    at com.lightbend.akka.sample.FileUploadTest$.delayedEndpoint$com$lightbend$akka$sample$FileUploadTest$1(FileUploadTest.scala:42)
    at com.lightbend.akka.sample.FileUploadTest$delayedInit$body.apply(FileUploadTest.scala:18)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at com.lightbend.akka.sample.FileUploadTest$.main(FileUploadTest.scala:18)
    at com.lightbend.akka.sample.FileUploadTest.main(FileUploadTest.scala)

我的代码是

package com.lightbend.akka.sample
import java.nio.file.Path

import scala.util.{ Failure, Success }
import scala.concurrent.Future

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl._

import akka.http.scaladsl.model.Multipart.FormData
import akka.http.scaladsl.marshalling.Marshal


object FileUploadTest  extends App {

  implicit val system = ActorSystem()
  import system.dispatcher // to get an implicit ExecutionContext into scope
  implicit val materializer = ActorMaterializer()
  case class FileToUpload(name: String, location: Path)

  def filesToUpload(): Source[FileToUpload, NotUsed] = ???

  val poolClientFlow = Http().cachedHostConnectionPool[FileToUpload]("akka.io")

  def createUploadRequest(fileToUpload: FileToUpload): Future[(HttpRequest, FileToUpload)] = {
    val bodyPart =
    // fromPath will use FileIO.fromPath to stream the data from the file directly
      FormData.BodyPart.fromPath(fileToUpload.name, ContentTypes.`application/octet-stream`, fileToUpload.location)

    val body = FormData(bodyPart) // only one file per upload
    Marshal(body).to[RequestEntity].map { entity => // use marshalling to create multipart/formdata entity
      // build the request and annotate it with the original metadata
      HttpRequest(method = HttpMethods.POST, uri = "http://example.com/uploader", entity = entity) -> fileToUpload
    }
  }

  // you need to supply the list of files to upload as a Source[...]
  filesToUpload()
    // The stream will "pull out" these requests when capacity is available.
    // When that is the case we create one request concurrently
    // (the pipeline will still allow multiple requests running at the same time)
    .mapAsync(1)(createUploadRequest)
    // then dispatch the request to the connection pool
    .via(poolClientFlow)
    // report each response
    // Note: responses will not come in in the same order as requests. The requests will be run on one of the
    // multiple pooled connections and may thus "overtake" each other.
    .runForeach {
    case (Success(response), fileToUpload) =>
      // TODO: also check for response status code
      println(s"Result for file: $fileToUpload was successful: $response")
      response.discardEntityBytes() // don't forget this
    case (Failure(ex), fileToUpload) =>
      println(s"Uploading file $fileToUpload failed with $`enter code here`ex")
  }
}

请帮我解释函数 filesToUpload 的定义,我尝试了很多方法但仍然无法通过。

1 个答案:

答案 0 :(得分:0)

假设您有三个要上传的文件:

/path/to/file1
/path/to/file2
/path/to/file3

实现filesToUpload()方法的一种方法是:

def filesToUpload(): Source[FileToUpload, NotUsed] = {
  import java.nio.file.Paths

  val files =
    List(FileToUpload("file1", Paths.get("/path/to/file1")),
         FileToUpload("file2", Paths.get("/path/to/file2")),
         FileToUpload("file3", Paths.get("/path/to/file3")))

  Source(files)
}