Подтвердить что ты не робот

Загрузка файла с использованием Akka HTTP

Я пытаюсь реализовать функцию загрузки файлов в своем приложении с использованием Akka HTTP. Я использую akka-stream версию 2.4.4.

Вот код (измененный 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.

Может ли кто-нибудь сообщить мне, что я делаю неправильно здесь?

4b9b3361

Ответ 1

Нет необходимости использовать стандартные блокирующие потоки, если для этой цели есть реактивные потоки:

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

Этот код загрузит поле fileUpload multipart в файл внутри каталога /tmp. Он просто выгружает содержимое входного источника в соответствующий файловый приемник, возвращая сообщение после завершения операции записи.

Вы также можете настроить диспетчер, используемый для источников и стоков FileIO, как описано в их скайдадоках.

Ответ 2

Если вам нужно только загрузить файл, но ничего не делать, пока загрузка не закончится в потоке файлов, то есть гораздо более простой способ:

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

См. Документы: https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/file-upload-directives/storeUploadedFile.html.

Ответ 3

Извините, я новичок и у меня проблема:

def insertPhoto(databaseDataProvider: DatabaseDataProvider, imagepath: String, data: Source[akka.util.ByteString, Any], token: String, event_id: String) = {
        var savefile = imagepath
        val dbuser = databaseDataProvider.existToken(token)
        if (dbuser.get != null) {
            val vyrobnicislo = dbuser.get.vyrobnicislo
            val iddb = dbuser.get.iddatabase
            val podtrzitko = "_"
            savefile = s"$savefile\\$vyrobnicislo\\doc$iddb$podtrzitko$event_id.jpg"
            implicit val materializer = ActorMaterializer.create(cz.evotech.QuickstartServer.system)
          val file = Paths.get(savefile)

          data.runWith(FileIO.toPath(file))

        }

      }

Размер сохраненного изображения равен 0. Какую ошибку я делаю? Пожалуйста спросите