2016-05-25 53 views
13

Sto cercando di implementare la funzionalità di caricamento dei file nella mia applicazione usando Akka HTTP. Sto usando la versione akka-stream2.4.4.Caricamento file tramite Akka HTTP

Ecco il codice (modificato da 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") 
      }*/ 
      } 
     } 
     } 
    } 
    } 

Questo codice sta lavorando bene e sta caricando il file al percorso indicato. Sto generando nuovi nomi di file aggiungendo UUID per assicurarmi che i nomi dei file siano univoci. Quindi ho bisogno di restituire il nuovo nome del file al chiamante. Tuttavia, questo metodo non restituisce sempre il nome file. A volte, sta finendo con Response has no content.

Qualcuno può farmi sapere cosa sto facendo male qui?

+1

Questa non è una risposta alla tua domanda, ma guarda http://doc.akka.io/docs/akka/2.4.6/scala/stream/stages-overview.html#file-io-sinks-and -sorse invece di scrivere manualmente su un file. Inoltre, l'utilizzo di Await.result all'interno di un percorso è davvero pessimo. –

+0

Lo guarderò. Ho provato con onSuccess invece di Await, bust stesso. Così ho provato con Await. Grazie per la risposta, lasciami provare il link. –

+0

@ RüdigerKlaehn Ho provato con FileIO, esiste ancora lo stesso problema :( –

risposta

14

Non v'è alcuna necessità di utilizzare il blocco standard flussi quando si dispone di flussi reattivi a tal fine:

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

Questo codice verrà quindi caricato fileUpload campo multipart in un file all'interno /tmp directory. Semplicemente scarica il contenuto della sorgente di input nel rispettivo sink di file, restituendo un messaggio al completamento dell'operazione di scrittura.

È inoltre possibile ritoccare il dispatcher utilizzato per le fonti e i sink , come descritto in their scaladocs.

+0

Anche con questo, a volte non ottengo la risposta :(. Mostra' La risposta era vuota '. L'unica differenza è che sto usando 2.4.4 invece di 2.4.6 –

+0

Come si verifica? Curl? È un file molto grande? –

+0

Sto testando l'estensione Chome, il client Advanced Rest. Il file non è molto grande. Ho provato con i file txt, sql, jpeg, png da 3kb a max 2 mb –