Resuming downloads


#1

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)?


#2

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…


#3

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.


#4

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.


#5

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.


#6

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”.


#7

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.


#8

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


#9

Oh yes, I added it in 1.46 I think.


#10

Ok, that’s really useful :slight_smile:

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


#11

[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.


#12

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.


#13

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


#14

Does it have any way to get the content length?