2017-08-03 16 views
1

Akka指令「fileUpload」是否將整個輸入實體文件複製到內存中?是否有一種方法可以將大文件分段上載爲1 GB而不消耗1 GB內存?Akka指令fileUpload將整個輸入實體文件複製到內存中?

 val uploadFile = File.createTempFile("uploadFile", ".txt") 
     extractRequestContext { ctx => 
     implicit val materializer = ctx.materializer 
     implicit val ec = ctx.executionContext 

     fileUpload("csv") { 
      case (metadata, byteSource) => 
      val sumF = byteSource.runFold(ByteString.empty) { case (acc, i) => acC++ i }.map(s => s.utf8String) 

      onSuccess(sumF) { sum => 
       Files.write(Paths.get(uploadFile.getAbsolutePath), sum.toString.getBytes) 
       logger.info(StatusCodes.OK + "Successfully completed fileUpload ") 
       complete(s"Successfully completed fileUpload") }} 
     } 

回答

0

您當前的方法收集整個文件到內存中。爲了避免這樣做,流的文件到磁盤中的sink

val uploadFile = File.createTempFile("uploadFile", ".txt") 

extractRequestContext { ctx => 
    implicit val materializer = ctx.materializer 
    implicit val ec = ctx.executionContext 

    fileUpload("csv") { 
    case (metadata, byteSource) => 
     val result = 
     byteSource.via(Framing.delimiter(ByteString("\n"), 10000)) 
        .runWith(FileIO.toPath(Paths.get(uploadFile.getAbsolutePath))) 

     onSuccess(result) { res => 
     logger.info(StatusCodes.OK + "Successfully completed fileUpload ") 
     complete(s"Successfully completed fileUpload") 
     } 
    } 
} 

您可能需要調整akka.http.server.parsing.max-content-length或定界符maximumFrameLength(10000在上面的例子)。

0

謝謝,問題與runFold,runWith解決了問題。

 extractDataBytes { bytes => 

        val path = Files.createTempFile(ATTACHMENT_NAME + "_" + "upload", "dat") 

        val futureWriteResult: Future[IOResult] = bytes.runWith(FileIO.toPath(path)) 


        onSuccess(futureWriteResult) { 
        case IOResult(count, Success(Done)) => UploadContent(path, parent, tenant, ATTACHMENT_NAME, async).execute() 
        case IOResult(_, Failure(ex)) => throw ex 
        } 
       } 
相關問題