简体   繁体   English

使用Akka HTTP上传文件

[英]File upload using Akka HTTP

I am trying to implement file upload functionality in my application using Akka HTTP. 我正在尝试使用Akka HTTP在我的应用程序中实现文件上载功能。 I am using akka-stream version 2.4.4 . 我使用的是akka-stream版本2.4.4

Here is the code (modified from akka-doc ) 这是代码(从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")
            }*/
          }
        }
      }
    }
  }

This code is working fine and is uploading the file to the given path. 此代码工作正常,并将文件上载到给定路径。 I am generating new file names by appending UUID to make sure that the file names are unique. 我通过附加UUID来生成新的文件名,以确保文件名是唯一的。 So I need to return the new file name to the caller. 所以我需要将新文件名返回给调用者。 However, this method is not returning the filename always. 但是,此方法始终不返回文件名。 Sometimes, it is finishing with Response has no content . 有时,它正在完成, Response has no content

Can anyone let me know what I am doing wrong here? 任何人都可以让我知道我在做错了什么吗?

There is no need to use the standard blocking streams when you have reactive streams for that purpose: 当您为此目的使用反应流时,无需使用标准阻塞流:

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

This code will upload fileUpload multipart field to a file inside /tmp directory. 此代码将fileUpload multipart字段上载到/tmp目录中的文件。 It just dumps the content of the input source to the respective file sink, returning a message upon the completion of the write operation. 它只是将输入源的内容转储到相应的文件接收器,在写入操作完成时返回一条消息。

You may also want to tweak the dispatcher used for FileIO sources and sinks, as described in their scaladocs . 您可能还想调整用于FileIO源和接收器的调度程序,如scaladocs中所述

If you need only uploading a file but not doing anything until upload finishes in the file stream, then there is much simpler way: 如果您只需要上传文件但在上传文件流完成之前没有做任何事情,那么有更简单的方法:

def tempDestination(fileInfo: FileInfo): File =
  File.createTempFile(fileInfo.fileName, ".tmp")

val route =
  storeUploadedFile("csv", tempDestination) {
    case (metadata, file) =>
      // do something with the file and file metadata ...
      file.delete()
      complete(StatusCodes.OK)
  }

See docs: https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/file-upload-directives/storeUploadedFile.html 请参阅文档: https//doc.akka.io/docs/akka-http/current/routing-dsl/directives/file-upload-directives/storeUploadedFile.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM