Как закрыть соединение после завершения многоступенчатой загрузки в VertX

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

введите описание изображения здесь