Kevin DiTraglia
Kevin DiTraglia

Reputation: 26058

Upload large file via URLSession

So I have some code I've been using to upload files in my app, along the lines of this:

var mutableURLRequest = URLRequest(url: url)
var uploadData = try! Data(contentsOf: dataUrl)
session.uploadTask(with: mutableURLRequest, from: uploadData).resume()

There's a little more to it than that, but those are the relevant parts. However I've noticed for some large video files Data(contentsOf: dataUrl) fails since the file is to big to load into memory. I want to restructure this so that I'm able to stream piece by piece to the server without ever having to load the whole file into memory.

I already have this figured out from my server, the only piece I haven't figured out is how to get a chunkSize piece from the data in a URL, without putting it into a data object. I essentially want this construct:

let chunkSize = 1024 * 1024
let offset = 0
let chunk = //get data from dataUrl of size chunkSize offset by offset

//Upload each chunk and increment offset

NSInputStream seemed promising in being able to do this, but I wasn't able to figure out the minimum set up in order to pull bytes from a file on disk in this fashion. What code can I use above to fill in the let chunk = line to do such a task?

Upvotes: 3

Views: 2743

Answers (1)

Kevin DiTraglia
Kevin DiTraglia

Reputation: 26058

I have a working solution, might need a little tweaking, but seems to work for big files I've tried:

public func getNextChunk() -> Data?{
    if _inputStream == nil {
        _inputStream = InputStream(url: _url)
        _inputStream?.open()
    }
    var buffer = [UInt8](repeating: 0, count: CHUNK_SIZE)
    var len = _inputStream?.read(&buffer, maxLength: CHUNK_SIZE)
    if len == 0 {
        return nil
    }
    return Data(buffer)
}

I also call _inputStream?.close() on deinit of my class that manages the chunking of a file on disk.

Upvotes: 1

Related Questions