Related: #1988 #2050 and probably few more.
So currently we have our own type for MultipartFormData, which is in fact a single part of that whole data (which is a bit different than the one from Alamofire):
public struct MultipartFormData {
/// Method to provide the form data.
public enum FormDataProvider {
case data(Foundation.Data)
case file(URL)
case stream(InputStream, UInt64)
}
public init(provider: FormDataProvider, name: String, fileName: String? = nil, mimeType: String? = nil) {
self.provider = provider
self.name = name
self.fileName = fileName
self.mimeType = mimeType
}
/// The method being used for providing form data.
public let provider: FormDataProvider
/// The name.
public let name: String
/// The file name.
public let fileName: String?
/// The MIME type
public let mimeType: String?
}
then we can pass an array of these in the Task:
enum Task {
...
case uploadMultipart([MultipartFormData])
...
}
and then Moya will transform this array into the proper, Alamofire-provided MultipartFormData:
extension MoyaProvider {
...
func sendUploadMultipart(_ target: Target, request: URLRequest, callbackQueue: DispatchQueue?, multipartBody: [MultipartFormData], progress: Moya.ProgressBlock? = nil, completion: @escaping Moya.Completion) -> CancellableToken {
let formData = RequestMultipartFormData()
formData.applyMoyaMultipartFormData(multipartBody)
...
}
}
but this way we lack the ability to provide the fileManager and boundary properties that Alamofire allows:
open class MultipartFormData {
...
public init(fileManager: FileManager = .default, boundary: String? = nil) {
self.fileManager = fileManager
self.boundary = boundary ?? BoundaryGenerator.randomBoundary()
bodyParts = []
}
...
}
So two solutions comes to my mind. First, just use the multipart body provided by Alamofire. Though I really like the way we have it as an enum and the transition from enum to structs might be more time-consuming.
So I think we could refactor a little bit what we have. How?
MultipartFormData to MultipartBodyPart (or something else, just an idea)MultipartFormData which could look like the following:struct MultipartFormData {
init(fileManager: FileManager = .default, boundary: String? = nil, parts: [MultipartBodyPart]) {
...
}
}
the callsite would change from:
enum MyTarget: Target {
var task: Task {
return .uploadMultipart([data, param])
}
}
to:
enum MyTarget: Target {
var task: Task {
return .uploadMultipart(MultipartFormData(parts: [data, param]))
}
}
Additionally, we could try and leverage ExpressibleByArrayLiteral so we could potentially not change the callsite at all for existing implementations and just add an option to provide these details.
thoughts? cc @Moya/contributors
any luck with this ?
@Mangoman3 I don't have time to implement this right now, but I would love to have this in the next release of Moya 15. If anyone would like to take a stab at it, I would be more than happy to help in a PR.
Most helpful comment
@Mangoman3 I don't have time to implement this right now, but I would love to have this in the next release of Moya 15. If anyone would like to take a stab at it, I would be more than happy to help in a PR.