【问题标题】:How to handle multipart request with Vapor 3如何使用 Vapor 3 处理多部分请求
【发布时间】:2018-03-26 10:18:03
【问题描述】:

我是一个蒸汽初学者,我选择从 Vapor 3-rc 开始,因为它似乎打破了与 Vaport 2 的变化。不幸的是,目前还没有完整的文档。

我目前正在尝试将一个简单的 txt 文件从 Postman 上传到我的 Vapor 3 本地服务器。

这是我的路线

let uploadController = FileUploadController()
router.post("uploadtxt", use: uploadController.uploadTXT)

和我的控制器

final class FileUploadController {
    func uploadTXT(_ req: Request) throws -> Future<String> {
        return try req.content.decode(MultipartForm.self).map(to: String.self, { form in
            let file = try form.getFile(named: "txtfile")
            return file.filename ?? "no-file"
        })
    }
}

首先,通过执行 Postman 请求,服务器返回:

{"error":true,"reason":"There is no configured decoder for multipart\/form-data; boundary=...}

通过研究源代码和limited documentation,看来我应该声明一个解码器来支持多部分传入请求。

所以我做到了:

var contentConfig = ContentConfig.default()
let decoder = FormURLDecoder()
contentConfig.use(decoder: decoder, for: .multipart)
services.register(contentConfig)

我使用了FormURLDecoder,因为它似乎是最符合我需要的 IMO 类,实现了BodyDecoder

现在它无限循环到 func decode&lt;T&gt;(_ type: T.Type) throws -&gt; T where T: DecodableFormURLSingleValueDecoder,我被困在这里,网络资源很少。

【问题讨论】:

    标签: swift vapor


    【解决方案1】:

    我结束了 Vapor slack,这是查找一些信息和一些帮助的好地方。

    解决方法很简单。与其使用req.content.decode(MultipartForm.self),不如使用MultipartForm.decode(from: req)(...已删除代码示例)

    编辑:

    正如@axello 所说,MultipartForm 不再存在。我现在使用req.content.decode(...) 方法来解析多部分数据。这个想法是创建一个反映您的 HTML 表单输入的对象。 Codable 会神奇地将数据映射到对象中。

    例如,使用这种形式:

    <form method="POST" action="upload" enctype="multipart/form-data" class="inputForm">
         <input type="name" name="filename">
         <input type="file" name="filedata">
         <input type="submit" name="GO" value="Send" class="send">
    </form>
    

    我创建了这个小结构

    fileprivate struct MyFile: Content {
        var filename: String
        var filedata: Data
    }
    

    而且,在我的控制器中:

    func uploadTXT(_ req: Request) throws -> Future<String> {
        return try req.content.decode(MyFile.self).map(to: String.self, { myFile in
            let filename = myFile.filename // this is the first input
            // ... and the second one:
            guard let fileContent = String(data: myFile.filedata, encoding: .utf8) else {
                throw Abort(.badRequest, reason: "Unreadable CSV file")
            }
            print(fileContent)
            return filename
        })
    }
    

    【讨论】:

    • 在这些小控制器中发生了很多事情,我发现它们很难准确地理解每个 sn-p 正在完成的工作。我只是问了一个问题,然后阅读了您的帖子。我想也许我也需要使用 multipartform (但我不确定如何)? stackoverflow.com/questions/49594004/…
    • 我刚看了你的帖子,你不需要多部分。 Multipart用于文件上传,您需要form-datax-www-urlencoded
    • 已在 Vapor 3.0.0 rc 2.4 中修复。文档更新:docs.vapor.codes/3.0/multipart/overview
    • 没有真正修复,因为 Multipart v 3.0.0 中不再存在 MultipartForm
    • 0 感谢您更新您的答案@Martin! Vapor 团队非常喜欢“快速行动并打破常规”。没关系,如果它同时被记录在案,但 Tanner 使用了一些魔法来解码表格,我无法理解它。所有其他的博客、魔法书等也都过时了。当然,其中大多数已经更新。仍然很高兴这个互联网智慧的 sn-p 现在也是正确的! ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 2018-10-26
    • 2010-11-03
    • 2014-02-05
    相关资源
    最近更新 更多