2016-05-25 8 views
13

Akka HTTPを使用してアプリケーションにファイルアップロード機能を実装しようとしています。私はakka-streamバージョン2.4.4を使用しています。ここAkka HTTPを使用したファイルアップロード

コード(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") 
      }*/ 
      } 
     } 
     } 
    } 
    } 

このコードが正常に動作して、所定のパスにファイルをアップロードされています。私はファイル名が一意であることを確認するためにUUIDを追加して新しいファイル名を生成しています。だから私は呼び出し元に新しいファイル名を返す必要があります。ただし、このメソッドは常にファイル名を返しません。場合によっては、Response has no contentで終了しています。

誰でも私がここで間違っていることを教えてもらえますか?

+1

これはあなたの質問に対する回答ではありませんが、http://doc.akka.io/docs/akka/2.4.6/scala/stream/stages-overview.html#file-io-sinks-andを参照してください。手動でファイルに書き込む代わりにソースを使用します。また、ルート内でAwait.resultを使用すると、本当に悪いスタイルです。 –

+0

それを見るでしょう。私はAwaitの代わりにonSuccessを試してみました。だから私はAwaitを試した。返信をありがとう、私はリンクを試してみましょう。 –

+0

@RüdigerKlaehn私はFileIOを試しましたが、同じ問題が残っています:( –

答えて

14

あなたがその目的のための反応性のストリームを持っている場合、標準のブロッキングストリームを使用する必要はありません。

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 
      } 
      } 
     } 
    } 
    } 

このコードは/tmpディレクトリ内のファイルにfileUploadマルチパートフィールドをアップロードします。入力ソースの内容をそれぞれのファイルシンクにダンプするだけで、書き込み操作の完了時にメッセージを返します。

their scaladocsに記載されているように、FileIOソースとシンクのディスパッチャを調整することもできます。

+0

時には応答が得られません:(それは'応答が空でした 'と表示されます。 2.4.3。 –

+0

どのようにテストしますか?Curl?非常に大きなファイルですか? –

+0

Chome Extension、Advanced Restクライアントを使ってテストしています。ファイルはそれほど大きくはありません.txt、sql、jpeg、pngファイルで試行しました。 。最小3kbから最大2メガバイト。 –

関連する問題