Search code examples
iosfile-uploadamazon-s3progress

Progressbar on file-upload to Amazon S3 for iOS?


I was using the services from Parse a while back, and they had implemented an amazing feature for uploading data, with a method something like this:

PFFile *objectToSave...; //An image or whatever, wrapped in a Parse-file
[objectToSave saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        //Do stuff after upload is complete
    } progressBlock:^(int percentDone) {
        [someLabel setText:[NSString stringWithFormat:@"%i%@", percentDone, @"%"]];
    }];

Which let me keep track of the file-upload. Since Parse only let me upload max 10mb files, I chose to move to the cloud-area to explore a bit. I've been testing with Amazon's S3-service now, but the only way I can find how to upload data is by calling [s3 putObject:request];. This will occupy the main thread until it's done, unless I run it on another thread. Either way, I have no idea of letting my users know how far the upload has come. Is there seriously no way of doing this? I read that some browser-API-version of S3's service had to use Flash, or set all uploads to go through another server, and keep track on that server, but I won't do either of those. Anyone? Thanks.

My users are supposed to be uploading video with sizes up to 15mb, do I have to let them stare at a spinning wheel for an unknown amount of time? With a bad connection, they might have to wait for 15 minutes, but they would stare at the screen in hope the entire time.


Solution

  • Seems like I didn't quite do my homework before posting this question in the first place. I found this great tutorial doing exactly what I was asking for. I would delete my question, but I'll let it stay just in case it might help other helpless people like myself.

    Basically, it had a delegate-method for this. Do something like this:

    S3PutObjectRequest *por = /* your request/file */;
    S3TransferManager *tm = /* your transfer manager */;
    
    por.delegate = self;
    tm.delegate = self;
    
    [tm upload: por];
    

    Then use this appropriately named delegate-method:

    -(void)request:(AmazonServiceRequest *)request 
        didSendData:(long long)bytesWritten 
        totalBytesWritten:(long long)totalBytesWritten 
        totalBytesExpectedToWrite:(long long)totalBytesExpectedToWrite
    {
        CGFloat progress = ((CGFloat)totalBytesWritten/(CGFloat)totalBytesExpectedToWrite);
    }
    

    It will be called for every packet it uploads or something. Just be sure to set the delegates.

    (Not sure if you need both delegates to be set though)