Using the iOS Dropbox SDK to Download Kernel Data

I have an iOS application that uses Core Data to permanently store data. I have included Dropbox as a way for users to back up the persistent file (appname.sqlite).

A UIButton calls a method to see if a file exists in Dropbox:

if([[DBSession sharedSession]isLinked]) { NSString *folderName = [[self.dateFormatter stringFromDate:[NSDate date]] stringByReplacingOccurrencesOfString:@"/" withString:@"-"]; NSString *destinationPath = [NSString stringWithFormat:@"/GradeBook Pro/Backup/%@/",folderName]; self.metadataIndex = METADATA_REQUEST_BACKUP; [self.restClient loadMetadata:destinationPath]; } 

The delegated method's loadedMetadata method initiates the download with the rev number of the existing file (if one exists).

 -(void) restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata { SAVE_CORE_DATA; NSString *folderName = [[self.dateFormatter stringFromDate:[NSDate date]] stringByReplacingOccurrencesOfString:@"/" withString:@"-"]; NSString *documentsDirectory = DOCUMENTS_DIRECTORY; NSString *sourcePath = [NSString stringWithFormat:@"%@/GradeBookPro.sqlite", documentsDirectory]; NSString *destinationPath = [NSString stringWithFormat:@"/GradeBook Pro/Backup/%@/",folderName]; [self.restClient uploadFile:@"GradeBookPro.sqlite" toPath:destinationPath withParentRev:[[metadata.contents lastObject]rev] fromPath:sourcePath]; } 

This works well for reasonably small files or large files over a perfect network connection, but any small download error cancels the whole process. I would like to switch to using batch loading methods, but I don’t understand how to actually β€œchunk” the .sqlite file.

I cannot find any sample applications that use the downloaded snippet that I can find out, and the documentation just says to provide the file in chunks.

So my questions are:

  • Is the chunked function the right choice to solve user problems when downloading large files over a possible network connection?

  • Can you tell me some sample code / application / documentation for a 'chunking' file? I am very comfortable with the Dropbox SDK.

Thanks!

+7
source share
1 answer

I am going to answer it myself just in case anyone has a different problem.

Turns out I did it a lot harder than I needed. The Dropbox SDK handles file fragmentation, so I just need to initiate the transfer and respond to delegate calls. Methods used:

To send a fragment of a file - for the first fragment use nil for uploadId and 0 for offset:

 - (void)uploadFileChunk:(NSString *)uploadId offset:(unsigned long long)offset fromPath:(NSString *)localPath; 

After sending the last fragment, use this method to commit the download:

 - (void)uploadFile:(NSString *)filename toPath:(NSString *)parentFolder withParentRev:(NSString *)parentRev fromUploadId:(NSString *)uploadId; 

I processed the delegate method as follows:

  - (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:[FileHelper localDatabaseFilePath] error:nil]fileSize]; if (offset >= fileSize) { //Upload complete, commit the file. [self.restClient uploadFile:DATABASE_FILENAME toPath:[FileHelper remoteDatabaseDirectory] withParentRev:self.databaseRemoteRevision 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:[FileHelper localDatabaseFilePath]]; } } 

Since the main problem I was trying to deal with was handling weak connections, I applied the delegation method to unsuccessful package downloads:

 - (void)restClient:(DBRestClient *)client uploadFileChunkFailedWithError:(NSError *)error { if (error != nil && (self.uploadErrorCount < DROPBOX_MAX_UPLOAD_FAILURES)) { self.uploadErrorCount++; NSString* uploadId = [error.userInfo objectForKey:@"upload_id"]; unsigned long long offset = [[error.userInfo objectForKey:@"offset"]unsignedLongLongValue]; [self.restClient uploadFileChunk:uploadId offset:offset fromPath:[FileHelper localDatabaseFilePath]]; } else { //show an error message and cancel the process } } 
+15
source

All Articles