2016-05-25 7 views
13

Ich versuche, Datei-Upload-Funktionalität in meiner Anwendung mit Akka HTTP zu implementieren. Ich verwende akka-stream Version 2.4.4. HierDatei-Upload mit Akka HTTP

ist der Code (modifiziert nach akka-doc)

path("fileupload") { 
    post { 
     extractRequestContext { 
     ctx => { 
      implicit val materializer = ctx.materializer 
      implicit val ec = ctx.executionContext 
      fileUpload("fileUpload") { 
      case (metadata, byteSource) => 
       val location = FileUtil.getUploadPath(metadata) 
       val updatedFileName = metadata.fileName.replaceAll(" ", "").replaceAll("\"", "") 
       val uniqFileName = uniqueFileId.concat(updatedFileName) 
       val fullPath = location + File.separator + uniqFileName 
       val writer = new FileOutputStream(fullPath) 
       val bufferedWriter = new BufferedOutputStream(writer) 

       val result = byteSource.map(s => { 
       bufferedWriter.write(s.toArray) 
       }).runWith(Sink.ignore) 

       val result1 = byteSource.runWith(Sink.foreach(s=>bufferedWriter.write(s.toArray))) 
       Await.result(result1, 5.seconds) 
       bufferedWriter.flush() 
       bufferedWriter.close() 
       complete(uniqFileName) 
      /*onSuccess(result) { x => 
       bufferedWriter.flush() 
       bufferedWriter.close() 
       complete("hello world") 
      }*/ 
      } 
     } 
     } 
    } 
    } 

Dieser Code funktioniert gut und wird die Datei in den angegebenen Pfad hochladen. Ich erzeuge neue Dateinamen durch Anhängen von UUID, um sicherzustellen, dass die Dateinamen eindeutig sind. Also muss ich dem Anrufer den neuen Dateinamen zurückgeben. Diese Methode gibt jedoch den Dateinamen nicht immer zurück. Manchmal endet es mit Response has no content.

Kann mir jemand sagen, was ich hier falsch mache?

+1

Dies ist keine Antwort auf Ihre Frage, aber schauen Sie in http://doc.akka.io/docs/akka/2.4.6/scala/stream/stages-overview.html#file-io-sinks-and -quellen statt manuell in eine Datei zu schreiben. Auch das Verwenden von Await.result in einer Route ist wirklich ein schlechter Stil. –

+0

Wird sich das ansehen. Ich habe versucht mit onSuccess statt Await, bust same. Also habe ich es mit Await versucht. Danke für die Antwort, lass mich den Link versuchen. –

+0

@ RüdigerKlaehn Ich habe versucht mit FileIO, noch das gleiche Problem existiert :( –

Antwort

14

Es gibt keine Notwendigkeit, die Standard-Sperrung zu verwenden ist Ströme, wenn Sie zu diesem Zweck reaktive Ströme haben:

path("fileUpload") { 
    post { 
     fileUpload("fileUpload") { 
     case (fileInfo, fileStream) => 
      val sink = FileIO.toPath(Paths.get("/tmp") resolve fileInfo.fileName) 
      val writeResult = fileStream.runWith(sink) 
      onSuccess(writeResult) { result => 
      result.status match { 
       case Success(_) => complete(s"Successfully written ${result.count} bytes") 
       case Failure(e) => throw e 
      } 
      } 
     } 
    } 
    } 

Dieser Code fileUpload mehrt Feld in eine Datei innerhalb /tmp Verzeichnis laden wird. Es wird nur der Inhalt der Eingabequelle an die jeweilige Dateisenke ausgegeben und nach Beendigung der Schreiboperation eine Nachricht zurückgesendet.

Sie können auch den Dispatcher für FileIO Quellen und Senken optimieren, wie in their scaladocs beschrieben.

+0

Auch damit bekomme ich manchmal nicht die Antwort :(. Es zeigt 'Die Antwort war leer'. Der einzige Unterschied ist, dass ich 2.4.4 anstelle von 2.4.6. –

+0

Wie testen Sie es? Curl? Ist es eine sehr große Datei? –

+0

Ich teste mit der Chome-Erweiterung, Advanced Rest Client. Die Datei ist nicht sehr groß. Versucht mit txt, sql, jpeg, png-Dateien Min. 3kb bis Max. 2 mb. –