3

I am uploading a file to a server, using NSStream APIs to read in chunks. I'm trying to display a progress bar showing upload progress. I'm unable to find a reliable solution for determining the number of bytes read into the file. Changing file and chunk size, I still keep getting either the total bytes, or something strange such as 93 or 212 for bytes read. Does anyone have any tips for trying to accomplish this? It seems like it should be simple.

  // create the write stream
    NSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:uploadTempFilename append:NO];
    [outputStream open];

    const char *UTF8String;
    size_t writeLength;
    UTF8String = [multipartBegin UTF8String];
    writeLength = strlen(UTF8String);

    size_t __unused actualWrittenLength;
    actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength];

    NSLog(@"actualWrittenLength1 %d bytes)", actualWrittenLength);//this will be 908
    // open the input stream
    const size_t bufferSize = 128 ;
    size_t readSize = 0;
    uint8_t *buffer = (uint8_t *)calloc(1, bufferSize);

    [inImageStream open];
    while ([inImageStream hasBytesAvailable]) {
        if (!(readSize = [inImageStream read:buffer maxLength:bufferSize])) {
            break;
        }


     size_t __unused actualWrittenLength;


        actualWrittenLength = [outputStream write:buffer maxLength:readSize];

        NSLog(@"actualWrittenLength2 %d bytes)", actualWrittenLength);//this always outputs 128, until the last call which will be something like 22


    }

    //NSLog(@"NSStreamFileCurrentOffsetKey %d", [outputStream valueForKey:NSStreamFileCurrentOffsetKey]);
    [inImageStream close];
    free(buffer);


    UTF8String = [multipartEnd UTF8String];
    writeLength = strlen(UTF8String);
    actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength];

    NSLog(@"actualWrittenLength3 %d bytes)", actualWrittenLength);//this will always be 42

[outputStream close];



    NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:uploadTempFilename];

    [HTTPRequest setContentType:contentType];
    return [HTTPRequest performMethod:@"POST" onURL:url withInputStream:inputStream knownContentSize:fileSize];
akaru
  • 6,299
  • 9
  • 63
  • 102

1 Answers1

2

Have you tried the property value of NSStreamFileCurrentOffsetKey?

CF-APIs may also be worth looking at.

If needed, you could subclass -[NSOutputStream write:maxLength:] to track the present position.

justin
  • 104,054
  • 14
  • 179
  • 226
  • Thanks. I'd like to keep it with Obj-C if possible. I've tried that call (see added code), but it's returning odd values. I'm not sure how to use the NSStreamFileCurrentOffsetKey; it didn't work with key-value calls. – akaru Jan 30 '12 at 19:28
  • 1
    What isn't Objective-C about this answer? – Abizern Jan 30 '12 at 19:32
  • @akaru check this out: http://www.cocoabuilder.com/archive/cocoa/211509-nsurlconnection-vs-cf-and-other-ideas.html – justin Jan 30 '12 at 20:16
  • @Abizern Justin referred me to Core Foundation APIs as well. This is what I was referring to. – akaru Jan 30 '12 at 20:32
  • CoreFoundation my be a C-type API but that doesn't make it non-Objective-C. – Abizern Jan 30 '12 at 20:38
  • 1
    Figured it out now. had to use propertyForKey: for NSStreamFileCurrentOffsetKey. Works nicely. Would still love to know why the -[NSOutputStream write:maxLength:] was returning strange values. – akaru Jan 30 '12 at 20:42
  • @akaru Just like a CFString is also an NSString, the CF/NS-Stream types are toll free bridged -- they really are the same type. CF APIs often give you access to the "expert parameters", and NS-APIs often give you access to many convenience variations and good support with other ObjC APIs. Toll free bridged types may be safely cast to their CF-NS counterparts without cost. Therefore, it's not uncommon to see CF APIs used to handle special cases when an appropriate ObjC method does not exist. It also takes a little time for NS types to catch up with CF features in some cases. – justin Jan 31 '12 at 01:22