Updated on 2026-09-22 GMT+08:00

Performing an Appendable Upload

Appendable upload allows you to upload an object in appending mode and then append data to the object. You can call appendObject to perform an appendable upload. Sample code is as follows:
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"FileName" ofType:@"FileSuffix"];
    //Append data for the first time.
    OBSAppendObjectWithFileRequest *request = [[OBSAppendObjectWithFileRequest alloc] initWithBucketName:@"bucketname" objectKey:@"objectname" uploadFilePath:filePath];
    request.position = [NSNumber numberWithLongLong:0];
    
    request.uploadProgressBlock =  ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
        NSLog(@"%0.1f%%",(float)floor((totalBytesExpectedToSend > 0) ? (totalBytesSent*10000/totalBytesExpectedToSend) : 0)/100);
        
    };
 
    __block NSString* nextPosition = nil;
    [client appendObject:request completionHandler:^(OBSAppendObjectResponse *response, NSError *error) {
        NSLog(@"%@",response);
        //Start position for next appending
        NSDictionary *temp = [response headers];
        nextPosition = [temp valueForKey:@"x-obs-next-append-position"];
        NSLog(@"nextPosition:%@", nextPosition);
    }];
    
    //Append data for the second time.
    request = [[OBSAppendObjectWithFileRequest alloc] initWithBucketName:@"bucketname" objectKey:@"objectname" uploadFilePath:filePath];
        
    if (nextPosition == nil) {
        // If x-obs-next-append-position is not returned for the first append upload, the data is appended from position 0 by default.
        nextPosition = @"0";
    }
    int nextPositionInt = [nextPosition intValue];
    request.position = [NSNumber numberWithInt:nextPositionInt];
    request.uploadProgressBlock =  ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
        NSLog(@"%0.1f%%",(float)floor((totalBytesExpectedToSend > 0) ? (totalBytesSent*10000/totalBytesExpectedToSend) : 0)/100);
        
    };
    [client appendObject:request completionHandler:^(OBSAppendObjectResponse *response, NSError *error) {
        NSLog(@"%@",response);
        //Start position for next appending
        NSDictionary *temp = [response headers];
        nextPosition = [temp valueForKey:@"x-obs-next-append-position"];
        NSLog(@"nextPosition:%@", nextPosition);
    }];
  • Objects uploaded using putObject, referred to as normal objects, can overwrite objects uploaded using appendObject, referred to as appendable objects. Data cannot be appended to an appendable object anymore once the object has been overwritten by a normal object.
  • When you upload an object for the first time in appendable mode, an exception will be reported (HTTP status code 409) if a common object with the same name is already present.
  • The ETag returned for an appendable upload is the ETag for the uploaded content, rather than that of the whole object.
  • Data appended each time can be up to 5 GB, and 10000 times of appendable uploads can be performed on a single object.
  • After an appendable upload is successful, you can obtain the start position for next appending using the following method or using the getObjectMetadata API.
    NSDictionary *temp = [response headers];NSString* nextPosition = [temp valueForKey:@"x-obs-next-append-position"];

    In the current SDK, the uploadFilePath parameter of the file upload APIs (OBSPutObjectWithFileRequest and OBSUploadFileRequest) only accepts file paths of the NSString type. Directly passing an NSURL object created with [NSURL fileURLWithPath:@"xxx"] is not supported. To use NSURL, obtain the file path string through [fileURL path] and then pass it to the uploadFilePath parameter.