Resuming downloads

Reading msdn.com, it seems that InternetSetFilePointer (in juce_seekInInternetFile) will fail if HttpOpenRequest was called with the flag INTERNET_FLAG_NO_CACHE_WRITE.

For now I’ve just removed it from the code on my computer, but maybe this should be an option (in case it’s useful for some purpose)?

But if you’re using the http stream to do dynamic get/post requests on a server, you don’t want it to cache the results…

You’re right, but InternetSetFilePointer won’t work otherwise.

But even this isn’t a working solution, apparently. It seems that InternetSetFilePointer does the same thing as is done in WebInputStream::setPosition, i.e. it downloads content until it reaches the specified position, and then returns.

So I’ll probably just have to adjust the http header to insert a “range:” value.

Weird, now InternetSetFilePointer did work with the cache flag. But since it still skips bytes, I’ll have to mess with the header.

I’ll have to adjust juce_openInternetFile for this, though. I’d like to change as little as possible to the Juce files, so I’m wondering if it would be best to add a callback or just set the range through parameters.

I don’t think you could rely on InternetSetFilePointer to work anyway. If you know some kind of http header flag that will resume on your particular server, I’d say use that.

Here’s my solution…

[code]const String hdr (“Content-Type: application/x-www-form-urlencoded”);

// inserted to support http resume
if (rangeStart > 0)
{
String hdrResume = “Range: bytes=” + String(rangeStart) + “-” + String(rangeEnd);
if (rangeEnd > rangeStart)
hdrResume += String(rangeEnd);
HttpAddRequestHeaders(request, (const char*)hdrResume, hdrResume.length(), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
}

if (HttpSendRequest (request, …[/code]

rangeStart and rangeEnd are parameters I’ve added to juce_openInternetFile (as well as WebInputStream’s constructor and URL::createInputStream).

If rangeEnd is -1 or 0, it’s not included in the range string, which means “download from start of range to the end of the file”.

But you don’t need to hack the juce code to do that - you can just pass in the extra header fields to URL::createInputStream.

Is that new in v1.46? I’m still using 1.45 atm, but this would be a reason to upgrade.

Oh yes, I added it in 1.46 I think.

Ok, that’s really useful :slight_smile:

Btw, I once implemented WebInputStream::getTotalLength(), if you’re interested in adding that.

[quote=“reflex”]Ok, that’s really useful :slight_smile:

Btw, I once implemented WebInputStream::getTotalLength(), if you’re interested in adding that.[/quote]

Sure - that’d be a handy addition.

First of all, this is WebInputStream::getTotalLength():

int64 getTotalLength() { return juce_getContentLength(handle); }

The Windows version of juce_getContentLength() looks like this:

[code]int juce_getContentLength (void handle)
{
DWORD result = 0;
const ConnectionAndRequestStruct
const crs = (const ConnectionAndRequestStruct*) handle;

if (crs != 0)
{
    DWORD index = 0;
    DWORD size = sizeof (result);

    HttpQueryInfo (crs->request,
                   HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
                   &result,
                   &size,
                   &index);
}

return (int) result;

}[/code]

And this is the mac version:

[code]int juce_getContentLength (void handle)
{
JUCE_HTTPSocketStream
const s = (JUCE_HTTPSocketStream*) handle;

if (s != 0)
    return s->contentLength;
	
return 0;

}[/code]

I’m not sure if the Windows version is done the best way, but it works.

Thanks - but on the mac, it’s all changed now, to use cocoa classes, so it doesn’t have a contentLength value any more…

Does it have any way to get the content length?