美文网首页码农的世界互联网科技Kotlin编程
Ktor踩坑,上传文件同时带参的问题

Ktor踩坑,上传文件同时带参的问题

作者: 何晓杰Dev | 来源:发表于2019-04-29 12:02 被阅读33次

    之前写过一篇Ktor响应请求并接受参数的(点击查看),在该篇文章内讲述了一种上传文件的方法,使用 call.receiveMultipart() 来对上传的文件进行接收。

    然而该案例仅有一个文件被上传,对部分同学造成了误导,有人给我提了这样一个问题:

    post("/upload") {
        val p = call.receiveParameters()
        val part = call.receiveMultipart()
        val desc = p["desc"] ?: ""
        val file = part.readPart() as? PartData.FileItem
        // save file...
    }
    

    用这样的代码来接受一个 post 请求,该请求的形式为:

    var fd = new FormData();
    fd.append('file', img);
    fd.append('desc', desc);
    $.ajax({
        url: '/req',
        type: 'POST',
        dataType: 'json',
        data: fd
    });
    

    “诶,看起来没错啊”,第一眼看到这代码时,我也觉得似乎是对的,但是实际跑一下,这份代码是会报错的,下面细细说来。

    首先,对于一个 post 请求,是要分清楚 Content-Type 的,虽然在请求里没有明说,但是我们应当可以推断出不同的请求会拥有的不同Contentt-Type。对于不带文件上传的请求,其 Content-Type 应当是 application/x-www-form-urlencoded,而对于带文件的,是 multipart/form-data,因此,对于带了文件又带了普通参数的请求,应当使用call.receiveMultipart() 来接收。

    那么接下来的问题就容易了,无非是如何取数据的问题,下面给两个函数:

    suspend fun MultiPartData.value(name: String) = 
        try { (readAllParts().filter { it.name == name }[0] as? PartData.FormItem)?.value } catch(e: Exception) { null }
    
    suspend fun MultiPartData.file(name: String) = 
        try { readAllParts().filter { it.name == name }[0] as? PartData.FileItem } catch(e: Exception) { null }
    

    然后在收到带文件上传的请求时,就可以这样做了:

    post("/upload") {
        val part = call.receiveMultipart()
        val desc = part.value("desc") ?: ""
        val file = part.file("file")
        // save file...
    }
    

    相关文章

      网友评论

        本文标题:Ktor踩坑,上传文件同时带参的问题

        本文链接:https://www.haomeiwen.com/subject/okgenqtx.html