When I upload a large file, the entire file is uploaded in a single shot, which is not what I expect since I've set MultipartFormData.BodyPart.bodyContentLength
.
I'm trying to upload a slice of length body.bodyContentLength
but I don't see any boundary constraining the MultipartFormData.writeBodyStream
method.
Is my assumption valid? Should the upload be limited to body.bodyContentLength
? Is this a bug on Alamofire? Is this a feature request?
Issue I created on Alamofire's repo: https://github.com/Alamofire/Alamofire/issues/3714
This proof of concept properly limited the request to bodyPart.bodyContentLength
as expected:
private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
let inputStream = bodyPart.bodyStream
inputStream.open()
defer { inputStream.close() }
var totalBytesRead = 0
var bytesLeftToRead: UInt64 = bodyPart.bodyContentLength
var bufferSize: Int = streamBufferSize
while inputStream.hasBytesAvailable && bytesLeftToRead > 0 {
if bytesLeftToRead < streamBufferSize {
// TODO: Review if it's ok to do this cast
bufferSize = Int(bytesLeftToRead)
}
var buffer = [UInt8](repeating: 0, count: bufferSize)
let bytesRead = inputStream.read(&buffer, maxLength: bufferSize)
if let streamError = inputStream.streamError {
throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
}
if bytesRead > 0 {
if buffer.count != bytesRead {
buffer = Array(buffer[0..<bytesRead])
}
try write(&buffer, to: outputStream)
bytesLeftToRead -= UInt64(bytesRead)
} else {
break
}
}
}
For reference I'm trying to upload to Kaltura video service provider. They provide a chunked upload approach, so we can have multiple requests each uploading a part of the stream.
High level pseudocode would look like this:
let inputStream = InputStream(URL: videoURL)
for chunk in chunks {
inputStream.skip(bytes: chunk.resumeAt) // extension implemented over InputStream to skip a number of bytes.
multipartFormData.append(inputStream,
withLength: chunk.size, // <<<<<<< THIS is set to `MultipartFormData.BodyPart.bodyContentLength` thus it should limit `MultipartFormData.writeBodyStream` while loop
name: uploadKey,
fileName: fileName,
mimeType: mimeType
)
alamofireSession.upload(multipartFormData: multipartData, ...)
}