0

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, ...)
}
henrique
  • 1,072
  • 10
  • 17

0 Answers0