cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Back again with another edition of 'How we use Dropbox', so find out how Emma uses to-do lists to get it all done here!

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

chunked uploading iOS

chunked uploading iOS

Marco N.2
New member | Level 1

Uploading large files is causing the -1101 error in my app frequently from my customers and also when I test. I am using a 50 Mbps internet connection on a 170 MB file size upload.
Any ideas or workarounds?
I was looking at using uploadFileChunk for iOS SDK but cannot find any examples.

Ok. I have tried to create the code in Objective-C and so far I keep getting

DropboxSDK: error making request to /1/chunkedupload - (404) No upload with uploadid

My code:

// parametersArray[0] is the File Name being uploaded. "MyFileName.zip"
// parametersArray[2] is the actual Path Plus File name from the iOS Device. "/path/morepath/morepath/MyFileName.zip"
[self.restClient uploadFileChunk:parametersArray[0] offset:0 fromPath:parametersArray[2]];

// Never gets called? <DBRestClientDelegate, DBSessionDelegate> I am using these delegates.
// Dropbox Delegate
- (void)restClient:(DBRestClient *)client uploadedFileChunk:(NSString *)uploadId newOffset:(unsigned long long)offset fromFile:(NSString *)localPath expires:(NSDate *)expiresDate {
    unsigned long long fileSize = [[[NSFileManager defaultManager]attributesOfItemAtPath:self.parametersArrayByChunks[2] error:nil] fileSize];

    if (offset >= fileSize)
    {
        //Upload complete, commit the file.
        NSLog(@"uploadId: %@", uploadId);
        [self.restClient uploadFile:self.parametersArrayByChunks[0] toPath:self.parametersArrayByChunks[1] withParentRev:nil fromUploadId:uploadId];
    }
    else
    {
        //Send the next chunk and update the progress HUD.
        //self.progressHUD.progress = (float)((float)offset / (float)fileSize);
        [self.restClient uploadFileChunk:uploadId offset:offset fromPath:self.parametersArrayByChunks[2]];

    }
}

Any thoughts?
Thank you.

7 Replies 7

Re: chunked uploading iOS

Greg-DB
Dropboxer

The first parameter to uploadFileChunk should be the upload ID, not the destination file name. The first time you call uploadFileChunk though, since you don't know the upload ID yet, you should just pass in nil.

Make sure to implement the error callback too:

- (void)restClient:(DBRestClient *)client uploadFileChunkFailedWithError:(NSError *)error;

Re: chunked uploading iOS

Greg-DB
Dropboxer

By the way, here's a quick sample I put together. I haven't tested this fully, so don't just ship this, but I believe the basics are right:

- (void) doTest {

    if ([[DBSession sharedSession] isLinked]) {
        NSLog(@"Running test...");

        // Write a file to the local documents directory
        NSString *text = @"Hello world. Usually something much longer here.";
        NSString *filename = @"working-draft.txt";
        NSString *localDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
        self.localPath = [localDir stringByAppendingPathComponent:filename];
        [text writeToFile:self.localPath atomically:YES encoding:NSUTF8StringEncoding error:nil];

        self.dbClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
        self.dbClient.delegate = self;

        // Start the upload. No upload ID known yet
        [self.dbClient uploadFileChunk:nil offset:0 fromPath:self.localPath];

    }


}

- (void)restClient:(DBRestClient *)client uploadedFileChunk:(NSString *)uploadId newOffset:(unsigned long long)offset
          fromFile:(NSString *)localPath expires:(NSDate *)expiresDate {

    NSLog(@"uploadedFileChunk: %@, newOffset: %llu, fromFile: %@, expires: %@", uploadId, offset, localPath, expiresDate);

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSDictionary *attrs = [fileManager attributesOfItemAtPath:self.localPath error: NULL];

    // in real use, there's probably a dangerous race condition here in checking the size each time, but this is just for demonstration purposes
    if (offset >= [attrs fileSize]) {
        // all data has been uploaded
        NSLog(@"Finishing upload...");
        [self.dbClient uploadFile:@"chunked_uploaded_file.txt" toPath:@"/" withParentRev:nil fromUploadId:uploadId];
    } else {
        // more data to upload
        NSLog(@"Continuing upload...");
        [self.dbClient uploadFileChunk:uploadId offset:offset fromPath:localPath];
    }

}

- (void)restClient:(DBRestClient *)client uploadFileChunkFailedWithError:(NSError *)error {

    NSLog(@"uploadFileChunkFailedWithError: %@", error);
    // TODO: retry

}

Re: chunked uploading iOS

Marco N.2
New member | Level 1

That is working great. I had to make minor adjustments for my situation.

One question, before using uploadFile I was able to upload a 170 MB file in about 2 minutes. Uploading by uploadFileChunk takes about 4+ minutes. Any suggestions on how to improve the upload speed?

// If I do not pass nil for offset I crash. 
 [self.dbClient uploadFileChunk:nil offset:nil fromPath:self.localPath];

Thank you so much for your help it is appreciated and this will solve a huge issue with my users with big data backups.

Re: chunked uploading iOS

Greg-DB
Dropboxer

When using chunked upload instead of single request uploading, there's extra overhead, due to the additional requests that need to be made. So, while it should be more reliable (i.e., less likely to timeout), it can take longer.

You can optimize this compromise for your scenario by choosing your chunk size (i.e., how much data you send per request) carefully. Larger chunks will reduce the overhead, but will be more likely to time out on uploading any particular chunk. Smaller chunks are less likely to time out, but introduce more overhead.

The iOS Core SDK uses a chunk size of 2 MB, and unfortunately doesn't expose a way to set a custom size though. (I'll consider this a feature request, however.) The SDK is open source though, so you can add the source directly and modify it if/as desired. The chunk size is passed to readDataOfLength in the uploadFileChunk in DBRestClient.m.

Re: chunked uploading iOS

Marco N.2
New member | Level 1

Sounds good. I am testing with different readDataOfLength sizes and I can see that even doubling it caused one of my uploads to timeout.

Thank you again for such great service.

Re: chunked uploading iOS

Greg-DB
Dropboxer

No problem I'm happy to help.

Also, I should mention, one of the advantages of chunked uploading is that even if one of the chunked uploading requests fails, you only have to re-send that one request's worth of data, as opposed to potentially almost the whole file in the single request upload scenario. That being the case, when tuning your chunk size, you may want to consider an occasional timeout acceptable if it makes the overall upload faster.

Re: chunked uploading iOS

Marco N.2
New member | Level 1

Great suggestion.

Poll
We love to learn from the educators who use Dropbox. Whether you teach kids, teens, adults or a combination of all three, we want to know what apps and integrations you use with Dropbox to help with teaching. Which of the ones below is your favorite, or most used tool?
Who's talking

Top contributors to this post

  • User avatar
    Marco N.2 New member | Level 1
  • User avatar
    Greg-DB Dropboxer
What do Dropbox user levels mean?
Need more support?