#scala #akka #akka-http
#scala #akka #akka-http
Вопрос:
Я пытаюсь загрузить файл через akka-http и заставил его работать со следующим фрагментом
def tempDestination(fileInfo: FileInfo): File =
File.createTempFile(fileInfo.fileName, ".tmp")
val route =
storeUploadedFile("csv", tempDestination) {
case (metadata, file) =>
//Do my operation on the file.
complete("File Uploaded. Status OK")
}
Но я бы также хотел отправить param1 / param2 в опубликованной форме.
Я попробовал следующее, и это работает, но мне приходится отправлять параметры через URL (http://host:port/csv-upload?userid=arvind )
(post amp; path("csv-upload")) {
storeUploadedFile("csv", tempDestination) {
case (metadata, file) =>
parameters('userid) { userid =>
//logic for processing the file
complete(OK)
}
}
}
Ограничение на размер файла составляет около 200-300 МБ. Я добавил следующее свойство в свой conf
akka{
http{
parsing{
max-content-length=200m
}
}
}
Есть ли способ, которым я могу получить параметры с помощью formFields
директивы?
Я попробовал следующее
fileUpload("csv") {
case (metadata, byteSource) =>
formFields('userid) { userid =>
onComplete(byteSource.runWith(FileIO.toPath(Paths.get(metadata.fileName)))) {
case Success(value) =>
logger.info(s"${metadata}")
complete(StatusCodes.OK)
case Failure(exception) =>
complete("failure")
Но с помощью приведенного выше кода я столкнулся со следующим исключением
java.lang.IllegalStateException: Substream Source cannot be materialized more than once
at akka.stream.impl.fusing.SubSource$$anon$13.setCB(StreamOfStreams.scala:792)
at akka.stream.impl.fusing.SubSource$$anon$13.preStart(StreamOfStreams.scala:802)
at akka.stream.impl.fusing.GraphInterpreter.init(GraphInterpreter.scala:306)
at akka.stream.impl.fusing.GraphInterpreterShell.init(ActorGraphInterpreter.scala:593)
Спасибо,
Арвинд
Комментарии:
1. Если вы хотите отправить файл некоторые данные в теле запроса, посмотрите,
multipart/-form data
у вас есть это сообщение об ошибке, потому чтоfileUpload
использует тело запроса, и когдаformFields
пытается прочитать тело запроса, читать нечего (тело уже было использовано (в виде потока)fileUpload
)2. Понял. Я попробую добавить пользовательский процессор для
multipart/form-data
и попытаюсь использовать файловый поток отдельно, а строковые параметры отдельно.
Ответ №1:
Я получил это, работая с чем-то вроде:
path("upload") {
formFields(Symbol("payload")) { payload =>
println(s"Server received request with additional payload: $payload")
def tempDestination(fileInfo: FileInfo): File = File.createTempFile(fileInfo.fileName, ".tmp.server")
storeUploadedFile("binary", tempDestination) {
case (metadataFromClient: FileInfo, uploadedFile: File) =>
println(s"Server stored uploaded tmp file with name: ${uploadedFile.getName} (Metadata from client: $metadataFromClient)")
complete(Future(FileHandle(uploadedFile.getName, uploadedFile.getAbsolutePath, uploadedFile.length())))
}
}
}
Полный пример:
https://github.com/pbernet/akka_streams_tutorial/blob/master/src/main/scala/akkahttp/HttpFileEcho.scala