Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting error when trying to upload a csv file with FileInputUpload #175

Closed
mkit opened this issue Jan 28, 2021 · 4 comments · Fixed by #228
Closed

Getting error when trying to upload a csv file with FileInputUpload #175

mkit opened this issue Jan 28, 2021 · 4 comments · Fixed by #228

Comments

@mkit
Copy link

mkit commented Jan 28, 2021

Describe the bug

Getting this error when uploading a CSV file:

14:12:32.529 [qtp897074030-43] ERROR kweb.Kweb - Exception while receiving websocket message
kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 38148: Expected string literal with quotes.
Use 'isLenient = true' in 'Json {}` builder to accept non-compliant JSON.

To Reproduce
Try to use the component with CSV files

Expected behavior
The file content is uploaded and no error is printed

@DineshSolanki
Copy link
Member

@mkit I'm not able to reproduce this, can you post your code?

@mkit
Copy link
Author

mkit commented Jan 28, 2021

I have the following component:

class EmailView : ComponentView {
    override val icon = "envelope"
    override val name = "Email Extractor"

    override fun renderTab(): ElementCreator<*>.() -> Unit = {
        div(fomantic.ui.fullHeight.padding(20, 20, 60, 20)).new {
//            div(fomantic.ui.top.attached.tabular.menu).new {
//                div(fomantic.active.item).text("Log")
//            }
            div(fomantic.ui.bottom.attached.active.tab.segment.fullHeight).text = KVar("Email Extractor Content")
            val csvFileInput = input(type = file, attributes = fomantic.ui.input.id("user_id_input"))
            FileFormInput().apply {
                setInputElement(csvFileInput)
                setAccept("CSV")
                onFileSelect {
                    retrieveFile {
                        println(it.base64Content)
                    }
                }
            }
        }
    }
}

That is used in (it is instantiated and member of the array: componentViews):

private fun Application.kwebFeature() {
    install(DefaultHeaders)
    install(Compression)
    install(WebSockets) {
        pingPeriod = Duration.ofSeconds(10)
        timeout = Duration.ofSeconds(30)

    }

    install(Kweb) {
        plugins = listOf(fomanticUIPlugin)
    }

    routing {
        get("/download/{id}") {
            call.respondBytes {
                "Test".toByteArray()
            }
        }
    }

    routing {
        get("/") {
            call.respondKweb {
                doc.head.new {
                    // Not required, but recommended by HTML spec
                    meta(name = "Description", content = "Admin")
                }
                doc.body.new {
                    doc.body.new {
                        div(
                            fomantic.ui.large.left.fixed.vertical.pointing.menu.padding(top = 61).id("main-menu")
                        ).new {
                            componentViews.forEach {
                                a(fomantic.item.withDataTabAttribute(it.javaClass.name)).text(it.name).new {
                                    if (it.icon.isNotBlank()) {
                                        i(fomantic.iconClass(it.icon))
                                    }
                                }
                            }
                        }
                        div(fomantic.ui.top.fixed.menu).new {
                            img(fomantic.ui.width(50).height(50).image.withImageSource("/static/fomantic/images/logo.png"))
                            div(fomantic.right.menu).new {
                                a(fomantic.item).new(position = 0) {
                                    i(fomantic.ui.iconClass("user"))
                                    p().text("Administrator")
                                }
                            }
                        }
                        div(fomantic.ui.fluid.fullHeight.padding(top = 61, left = 251)).new {
                            componentViews.forEach {
                                div(fomantic.ui.fluid.fullHeight.tab.withDataTabAttribute(it.javaClass.name)).new {
                                    it.renderTab()()
                                }
                            }
                        }
                        execute("\$('#main-menu .item').tab()")
                        execute("\$('.activating.element').popup()")
                        execute(
                            "\$('#main-menu .column.segment').on('click', function() {\n" +
                                    "    var tabName = \$(this).attr('data-tab');\n" +
                                    "    \$.tab('change tab', tabName);\n" +
                                    "    \$('#main-menu .item').removeClass('active');\n" +
                                    "    \$('#main-menu .item[data-tab=\"'+ tabName +'\"]').addClass('active');\n" +
                                    "  })"
                        )
//                execute("\$('.ui.accordion').accordion()")
                    }
                }
            }
        }
    }
}

@DineshSolanki
Copy link
Member

surprisingly retriveFile is not working for me anymore, WebSocket message is sent from browser correctly also in CSV case, but somehow nothing is being hit in the retriveFile

@creekpld
Copy link

creekpld commented Feb 24, 2021

Hi, I have the same issue, and here is my log from the Kweb backend.

Looks like the JSON decoder expects a "string literal with quotes" on the fileSize value.

Unfortunately, I have no experience with kotlinx serialization but maybe this helps someone. ;)

2021-02-24 10:21:04.857 [DefaultDispatcher-worker-6] INFO  kweb.html.fileUpload.FileFormInput - null
2021-02-24 10:21:04.866 [DefaultDispatcher-worker-6] DEBUG kweb.Kweb - Message received from client
2021-02-24 10:21:04.866 [DefaultDispatcher-worker-6] DEBUG kweb.Kweb - Message received: Client2ServerMessage(id=wlNQIs, hello=null, error=null, callback=C2SCallback(callbackId=9475543, data={"base64Content":"data:;base64,SGVsbG8sIFdvcmxkIQ==","fileSize":13,"fileName":"test.log"}), historyStateChange=null)
2021-02-24 10:21:04.866 [DefaultDispatcher-worker-6] INFO  kweb.html.fileUpload.FileFormInput - Result is {"base64Content":"data:;base64,SGVsbG8sIFdvcmxkIQ==","fileSize":13,"fileName":"test.log"}
2021-02-24 10:21:04.887 [DefaultDispatcher-worker-6] ERROR kweb.Kweb - Exception while receiving websocket message
kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 64: Expected string literal with quotes.
Use 'isLenient = true' in 'Json {}` builder to accept non-compliant JSON.
JSON input: {"base64Content":"data:;base64,SGVsbG8sIFdvcmxkIQ==","fileSize":13,"fileName":"test.log"}
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
	at kotlinx.serialization.json.internal.JsonReader.fail(JsonReader.kt:338)
	at kotlinx.serialization.json.internal.JsonReader.takeStringQuoted(JsonReader.kt:170)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:213)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58)
	at kweb.html.fileUpload.FileUpload$$serializer.deserialize(FileUpload.kt)
	at kweb.html.fileUpload.FileUpload$$serializer.deserialize(FileUpload.kt:6)
	at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:63)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:32)
	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:85)
	at kweb.html.fileUpload.FileFormInput$retrieveFile$1.invoke(FileFormInput.kt:47)
	at kweb.html.fileUpload.FileFormInput$retrieveFile$1.invoke(FileFormInput.kt:12)
	at kweb.Kweb.listenForWebsocketConnection(Kweb.kt:311)
	at kweb.Kweb$listenForWebsocketConnection$1.invokeSuspend(Kweb.kt)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Using:

  • kotlin 1.4.30
  • kweb 0.8.5
  • ktor 1.4.3
  • kotlinx-serialization-json 1.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants