#java #kotlin #upload #vert.x
#java #kotlin #загрузка #vert.x
Вопрос:
Я создаю потоковую загрузку в VertX, чтобы я мог передавать потоковую загрузку непосредственно в корзину Google Cloud / AWS S3, но загрузка, похоже, никогда не заканчивается при просмотре вкладки сети в браузере.
Это тестовая форма загрузки, которую я использую:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<input type="text" value="blah">
<input multiple type="file">
</form>
<div>
</div>
<script>
let input = document.querySelector("input[type='file']")
let div = document.querySelector("div")
input.addEventListener("change", event => {
let files = event.target.files
console.log(files)
const formData = new FormData()
for (let file of files) {
formData.append(file.name, file)
formData.append("blah", "blah")
}
window.fetch("http://localhost:11111/le-upload-test?testing=true", {
method: "POST",
body: formData
}).then(response => {
div.innerHTML = ""
div.append(`${response.statusText} - ${response.status}`)
console.log(response)
})
})
</script>
</body>
</html>
В серверной части,
class MyServer(
val port: Int,
) : CoroutineVerticle() {
val log = LoggerFactory.getLogger(this.javaClass)
init {
Vertx.vertx()?.deployVerticle(this)
?: throw Exception("Failed to start VertX")
}
override suspend fun start() {
vertx.createHttpServer().requestHandler { req ->
println(req.path())
if (req.path() == "/le-upload-test") {
req.isExpectMultipart = true
req.uploadHandler { upload ->
println("==================")
println(req.params())
println(upload.filename())
println("==================")
upload.handler { chunk ->
println("chunk.length=${chunk.length()}")
println("total.read=${req.bytesRead()}")
}
}
}
}.listen(port)
}
}
fun main() {
MyServer(
port = 11111,
)
}
При загрузке нескольких файлов это правильно выводит:
/le-upload-test
==================
testing=true
Screenshot_20201026_211340.png
==================
chunk.length=239
total.read=422
chunk.length=8192
total.read=8614
chunk.length=8192
...
==================
testing=true
Screenshot_20201026_181456.png
==================
chunk.length=192
total.read=74150
chunk.length=7770
total.read=81920
...
В какой момент я должен звонить req.response.end("...")
?
Если я не перезапущу сервер, браузер просто зависнет там на неопределенный срок?
Я пытался делать:
req.uploadHandler { upload ->
val contentLength = req.getHeader("Content-Length")
upload.handler { chunk ->
if (req.bytesRead().toString() == contentLength) {
println("DONE!!")
req.response().setStatusCode(200).end("DONE")
}
}
}
Это правильно печатает DONE, когда все байты обработаны, но затем браузер показывает сбой, EMPTY RESPONSE
.
Добавление upload.endHandler
после upload.handler
upload.endHandler { end ->
println("DONE!!!")
req.response().setStatusCode(200).end("TEST")
}
правильно ли печатается DONE!!!
часть, когда обрабатываются все байты, но также никогда не закрывается соединение для загрузки со статусом 200.
Ответ №1:
Удалось заставить его работать, кажется, не хватало только заголовка CORS
override suspend fun start() {
vertx.createHttpServer().requestHandler { req ->
println(req.path())
try {
if (req.path() == "/le-upload-test") {
req.response().putHeader("Access-Control-Allow-Origin", "*")
req.isExpectMultipart = true
req.uploadHandler { upload ->
req.endHandler {
req.response().end("BLAH!!")
println("DONE")
}