I'm a vapor beginner and I chose to start with Vapor 3-rc because it seems to break change from Vaport 2. Unfortunately, there isn't a complete documentation for now.
I'm currently trying to upload a simple txt file from Postman to my Vapor 3 local server.
Here's my route
let uploadController = FileUploadController()
router.post("uploadtxt", use: uploadController.uploadTXT)
and my controller
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"
})
}
}
First, by executing the Postman request, the server returns:
{"error":true,"reason":"There is no configured decoder for multipart\/form-data; boundary=...}
By investigating the source code and the limited documentation on this, it seems that I should declare a decoder to support multipart incoming requests.
So I did:
var contentConfig = ContentConfig.default()
let decoder = FormURLDecoder()
contentConfig.use(decoder: decoder, for: .multipart)
services.register(contentConfig)
I used FormURLDecoder
because it seemed to be the closest class for my needs IMO, implementing BodyDecoder
Now it infite-loops into func decode<T>(_ type: T.Type) throws -> T where T: Decodable
of FormURLSingleValueDecoder
, and I'm stuck here with very few web resource.
I ended on the Vapor slack, which is a good place to find some info & a bit of help.
The solution is quite simple. Instead of usingreq.content.decode(MultipartForm.self)
, prefer useMultipartForm.decode(from: req)
(...deleted code sample)EDIT:
AS @axello said,
MultipartForm
does not exist anymore. I'm now usingreq.content.decode(...)
method to parse the multipart data. The idea is to create an object that reflects your HTML form inputs. And Codable will magically map the data into the object for you.For example, with this form:
I created this small struct
And, in my controller: