Getting progress of HTTP POST as it's being UPLOADED

  • I need to get the status of a POST request as it's being uploaded. I need
    this information so that I can display how many bytes have been uploaded so
    far, and how many are left to be written.

    I've gone as far as to use setHTTPBodyStream, subclassing
    NSMutableURLRequest, then overriding the delegate method stream:handleEvent:
    so I can track the progress of the stream that way. I did so because
    NSURLRequest is supposed to set the delegate of the NSInputStream as itself,
    according to the documentation. Even when I attempt this, it seems the
    delegate method in my subclass is never called:

    #import "VEMutableURLRequest.h"

    @implementation VEMutableURLRequest

    - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {

        NSLog(@"Stream Event!!");
    }

    - (void)setHTTPBodyStream:(NSInputStream *)inputStream {
        [super setHTTPBodyStream:inputStream];
        [[self HTTPBodyStream] setDelegate:self];
        NSLog(@"setHTTPBodyStream done");
        NSLog(@"delegate of Stream: %@", [[[self HTTPBodyStream] delegate]
    className]);
    }

    @end

    The console does show the log information for setHTTPBodyStream:, but it
    does not show any log information for stream:handleEvent:. I am loading the
    request this way:

    NSURLResponse* response;
    NSError* error;
    NSData* result = [NSURLConnection sendSynchronousRequest:postRequest
    returningResponse:&response error:&error];

    The POST request is sent correctly, and there's no hitch in the
    communication with the server. My only problem is that I can't seem to get
    any delegate messages from the HTTPBodyStream.

    Please, if anyone could please help me with this problem, I would really,
    really appreciate it. Is this even possible with NSURLRequest? If not, how
    would I go about doing so using a different framework (such as CURLHandle)?

    Thanks in advance.

    Daniel
  • Daniel,

    > I need to get the status of a POST request as it's being uploaded.
    > I need
    > this information so that I can display how many bytes have been
    > uploaded so
    > far, and how many are left to be written.
    >

    This is what I've done....

    Setup CFHTTPRequest using CFHTTPMessageCreateRequest and associated
    functions such as CFHTTPMessageSetHeaderFieldValue,
    CFReadStreamCreateWithFile,
    CFReadStreamCreateForStreamedHTTPRequest,  etc

    To get the bytes uploaded, create a timer and call the following
    periodically during the upload:

      CFNumberRef byteCount = (CFNumberRef)CFReadStreamCopyProperty
    (httpReqStream, kCFStreamPropertyHTTPRequestBytesWrittenCount);

    this doesn't quite give exactly what we want as it returns the bytes
    written to the kernel buffer, not the bytes as they are transmitted
    from the buffer.
    So your first read of this property will give something like 32k or
    64k when the buffer is initially filled, then will increase as the
    data is transmitted and the buffer refilled.

    >
    > Please, if anyone could please help me with this problem, I would
    > really,
    > really appreciate it. Is this even possible with NSURLRequest? If
    > not, how
    > would I go about doing so using a different framework (such as
    > CURLHandle)?
    >
    > Thanks in advance.
    >
    > Daniel
    >

    I'm pretty sure the progress can't be obtained using NSURLRequest. I
    tried - I just can't remember why. So definitely use the CFHTTP.....
    set of methods.

    Cheers
    Gary
  • Thanks a lot for your comments, I really appreciate it. Unfortunately, I
    don't have much experience working with the Core Foundation, especially with
    its networking functions. Do you happen to have some sample code that would
    show setting up a basic request, obtaining the stream, and then getting the
    byte count? I can't seem to find the
    CFReadStreamCreateForStreamedHTTPRequest function, and I'm not sure if I can
    make heads or tails of HTTP requests using CF.

    If you or anyone could please give me some more hints, it would be a huge
    help. Thanks for your advice thus far.

    Daniel

    On 8/30/06, Gary Fielke <gary...> wrote:
    >
    > Daniel,
    >
    >> I need to get the status of a POST request as it's being uploaded.
    >> I need
    >> this information so that I can display how many bytes have been
    >> uploaded so
    >> far, and how many are left to be written.
    >>
    >
    > This is what I've done....
    >
    > Setup CFHTTPRequest using CFHTTPMessageCreateRequest and associated
    > functions such as CFHTTPMessageSetHeaderFieldValue,
    > CFReadStreamCreateWithFile,
    > CFReadStreamCreateForStreamedHTTPRequest,  etc
    >
    > To get the bytes uploaded, create a timer and call the following
    > periodically during the upload:
    >
    > CFNumberRef byteCount =
    > (CFNumberRef)CFReadStreamCopyProperty
    > (httpReqStream, kCFStreamPropertyHTTPRequestBytesWrittenCount);
    >
    > this doesn't quite give exactly what we want as it returns the bytes
    > written to the kernel buffer, not the bytes as they are transmitted
    > from the buffer.
    > So your first read of this property will give something like 32k or
    > 64k when the buffer is initially filled, then will increase as the
    > data is transmitted and the buffer refilled.
    >
    >>
    >> Please, if anyone could please help me with this problem, I would
    >> really,
    >> really appreciate it. Is this even possible with NSURLRequest? If
    >> not, how
    >> would I go about doing so using a different framework (such as
    >> CURLHandle)?
    >>
    >> Thanks in advance.
    >>
    >> Daniel
    >>
    >
    > I'm pretty sure the progress can't be obtained using NSURLRequest. I
    > tried - I just can't remember why. So definitely use the CFHTTP.....
    > set of methods.
    >
    > Cheers
    > Gary
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<dtkurtz...>
    >
    > This email sent to <dtkurtz...>
    >

    --
    Daniel Kurtz
    Phone: (508)789-8048

    Dual BS in Computer Science and Cognitive Psychology
    College of Computer and Information Science
    Northeastern University, Boston, MA, USA
  • Daniel,

    Yes, the docs for  CFReadStreamCreateForStreamedHTTPRequest are not
    exactly easy to find!
    Cmd-double-leftclick on the function in XCode will open
    CFHTTPStream.h with some notes on it.
    Do a search for this function on the networking list and you'll find
    some tips - such as this one:

    http://lists.apple.com/archives/Macnetworkprog/2005/Dec/msg00066.html

    Before that though, start with the CFNetwork Programming Guide:
    http://developer.apple.com/documentation/Networking/Conceptual/
    CFNetwork/index.html
    There's plenty of sample code there to get started including creating
    and setting up a request.

    Cheers
    Gary

    > Thanks a lot for your comments, I really appreciate it.
    > Unfortunately, I
    > don't have much experience working with the Core Foundation,
    > especially with
    > its networking functions. Do you happen to have some sample code
    > that would
    > show setting up a basic request, obtaining the stream, and then
    > getting the
    > byte count? I can't seem to find the
    > CFReadStreamCreateForStreamedHTTPRequest function, and I'm not sure
    > if I can
    > make heads or tails of HTTP requests using CF.
    >
    > If you or anyone could please give me some more hints, it would be
    > a huge
    > help. Thanks for your advice thus far.
    >
    > Daniel
    >
    >
    > On 8/30/06, Gary Fielke <gary...> wrote:
    >>
    >> Daniel,
    >>
    >>> I need to get the status of a POST request as it's being uploaded.
    >>> I need
    >>> this information so that I can display how many bytes have been
    >>> uploaded so
    >>> far, and how many are left to be written.
    >>>
    >>
    >> This is what I've done....
    >>
    >> Setup CFHTTPRequest using CFHTTPMessageCreateRequest and associated
    >> functions such as CFHTTPMessageSetHeaderFieldValue,
    >> CFReadStreamCreateWithFile,
    >> CFReadStreamCreateForStreamedHTTPRequest,  etc
    >>
    >> To get the bytes uploaded, create a timer and call the following
    >> periodically during the upload:
    >>
    >> CFNumberRef byteCount =
    >> (CFNumberRef)CFReadStreamCopyProperty
    >> (httpReqStream, kCFStreamPropertyHTTPRequestBytesWrittenCount);
    >>
    >> this doesn't quite give exactly what we want as it returns the bytes
    >> written to the kernel buffer, not the bytes as they are transmitted
    >> from the buffer.
    >> So your first read of this property will give something like 32k or
    >> 64k when the buffer is initially filled, then will increase as the
    >> data is transmitted and the buffer refilled.
  • > I need to get the status of a POST request as it's being uploaded.
    > I need
    > this information so that I can display how many bytes have been
    > uploaded so
    > far, and how many are left to be written.

    You might be interested in some old code I wrote for exactly that
    purpose, feel free to take everything you want.

    http://dev.lorem-ipsum.at/LIHTTPUpload.h
    http://dev.lorem-ipsum.at/LIHTTPUpload.m

    To be honest, I am not perfectly sure if you could answer questions
    for the code,
    I never used in production (it was more of a experiment) it but it
    worked quite good.

    Yours,
    Ferdinand