Download only first x bytes of a file or stream - regardless of Range support on server?

35 views
Skip to first unread message

johnswan

unread,
Jan 2, 2011, 7:05:56 AM1/2/11
to ASIHTTPRequest
Hi,

I am working on an iOS app and have a problem:

I have a large selection of URLs - some serve short text files and
some are media streams (which have no end - they just keep going).

I need to catalog these URLs, by determining which type of data they
are. I can identify the type by downloading the first (say) 65535
bytes and looking in there. However, if the URL serves an infinitely
long stream, the download will never end. As I am downloading
synchronously (with a time out of 10 seconds), this will be a problem
as the UI will hang until I eventually run out of memory.

How can I ensure that only the first X bytes are downloaded with
ASIHTTPRequest? I understand that I can set the Range request header,
but that this is dependent on the server supporting Range. I don't
control these servers and cannot know if they support Range or not,
but if I rely on Range then my app will break whenever I try to
download the first X bytes from a server which doesn't support Range.

Is there a way to instruct ASIHTTPRequest to stop downloading after
the first X bytes?

Thanks
John

Ben Copsey

unread,
Jan 3, 2011, 6:43:10 AM1/3/11
to asihttp...@googlegroups.com
Hi John

Probably the best approach would be to subclass ASIHTTPRequest, and override handleBytesAvailable with something like this:

- (void)handleBytesAvailable
{
[super handleBytesAvailable];
if ([self totalBytesRead] >= 65535) {
[self cancelLoad];
[self handleStreamComplete];
}
}

Untested, but let me know if you get stuck.

Best

Ben

johnswan

unread,
Jan 3, 2011, 3:15:09 PM1/3/11
to ASIHTTPRequest
Hi Ben,

Thanks so much for the detailed reply.

One thing, however the [self handleStreamComplete] throws an
EXC_BAD_ACCESS. I can't see where exactly, but it's something to do
with reading the response headers.

Stack trace:

CFReadStreamCopyProperty + 33
-[ASIHTTPRequest readResponseHeaders] + 133 (ASIHTTPRequest.m:2045)
-[ASIHTTPRequest handleStreamComplete] + 157 (ASIHTTPRequest.m:3136)

Is this something that I can fix?

Thanks
John

Ben Copsey

unread,
Jan 6, 2011, 1:50:35 PM1/6/11
to asihttp...@googlegroups.com
Hi John

>> Probably the best approach would be to subclass ASIHTTPRequest, and override handleBytesAvailable with something like this:
>>
>> - (void)handleBytesAvailable
>> {
>> [super handleBytesAvailable];
>> if ([self totalBytesRead] >= 65535) {
>> [self cancelLoad];
>> [self handleStreamComplete];
>> }
>>
>> }
>>
>> Untested, but let me know if you get stuck.

> Thanks so much for the detailed reply.


>
> One thing, however the [self handleStreamComplete] throws an
> EXC_BAD_ACCESS. I can't see where exactly, but it's something to do
> with reading the response headers.
>
> Stack trace:
>
> CFReadStreamCopyProperty + 33
> -[ASIHTTPRequest readResponseHeaders] + 133 (ASIHTTPRequest.m:2045)
> -[ASIHTTPRequest handleStreamComplete] + 157 (ASIHTTPRequest.m:3136)

Ah, ok, looks like it's trying to get to the CFNetwork request object after we've released it.

Possibly just doing this instead:

- (void)handleBytesAvailable
{
[super handleBytesAvailable];
if ([self totalBytesRead] >= 65535) {

[self handleStreamComplete];
}
}

I think handleStreamComplete should handle cancelling the load for you, and I would guess this will prevent the problem above - this seemed to work in a quick test for me, but I haven't really tested properly.

Best

Ben

johnswan

unread,
Jan 11, 2011, 6:04:26 PM1/11/11
to ASIHTTPRequest
Hi Ben,

Many thanks! So far, it seems to work really well!

Best regards
John
Reply all
Reply to author
Forward
0 new messages