7

永続データストレージにコアデータを使用するiOSアプリがあります。ユーザーが永続ストアファイル(appname.sqlite)のバックアップを実行する方法としてDropboxを統合しました。

UIButtonはメソッドを呼び出して、ファイルが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];
            }

ロードされたMetadataデリゲートメソッドは、既存のファイルのリビジョン番号(存在する場合)を使用してアップロードを開始します。

-(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];               
}

これは、完全なネットワーク接続を介した適度に小さいファイルまたは大きいファイルに対してはうまく機能しますが、アップロード中に小さなエラーが発生すると、プロセス全体がキャンセルされます。チャンクアップロードメソッドの使用に切り替えたいのですが、.sqliteファイルの「チャンク」を実際に実行する方法がわかりません。

学習できるチャンクアップロードを使用しているサンプルアプリが見つからないようです。ドキュメントには、ファイルをチャンクで提供するように記載されているだけです。

だから、私の質問は次のとおりです。

  1. チャンクアップロードは、むらのあるネットワーク接続を介して大きなファイルをアップロードする際のユーザーの問題に対処するための正しいアプローチですか?

  2. ファイルを「チャンク」するためのサンプルコード/アプリ/ドキュメントを教えてもらえますか?私はDropboxSDKにかなり慣れています。

ありがとう!

4

1 に答える 1

15

他の誰かが同じ問題を抱えている場合に備えて、私はこれに自分で答えるつもりです。

私はこの方法を必要以上に難しくしていたことがわかりました。Dropbox SDKはファイルのチャンク処理を処理するため、転送を開始してデリゲート呼び出しに応答する必要がありました。使用される方法は次のとおりです。

ファイルチャンクを送信するには、最初のチャンクに、uploadIdにnilを使用し、オフセットに0を使用します。

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

最後のチャンクを送信した後、次のメソッドを使用してアップロードをコミットします。

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

デリゲートメソッドを次のように処理しました。

    - (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]];
        }
    }

私が対処しようとしていた主な問題は接続不良の処理であったため、失敗したチャンクアップロードに対してデリゲートメソッドを実装しました。

- (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
    }
}
于 2012-12-09T18:08:48.567 に答える