urltask(
URL
,
OPTION
,
VALUE
)

The urltask( function asynchronously loads a resource from the internet.


Parameters

This function has three parameters:

url – The address of the resource to be loaded, for example "http://www.apple.com".

option – One or more options/value pairs can be included after the url parameter. These pairs specify things like what file or variable the resource should be placed into, what code (if any) to run when the resource load is complete, how progress should be reported, etc. See the description below for details on each option.

value – The value associated with an option/value pair. See below for details.


Description

This function loads a resource from the internet, for example a web page or an image. Unlike the loadurl( and posturl( functions, the urltask( function is asynchronous. This means that the resource is downloaded in the background, and Panorama can perform other operations at the same time. In other words, Panorama does not “hang” while the item is downloaded – the user can use the mouse and keyboard normally, even start other downloads with additional urltask( functions.

Unlike the loadurl( and posturl( functions, the result of the urltask( function isn’t the item being downloaded. Instead, this function returns a unique ID that identifies the url task. This ID can be used to cancel the url task before it finishes. If you don’t intend to cancel the task, you don’t need to keep the ID. Cancelling a task is discussed in more detail below.

Specifying the Resource Destination

When the resource has finished downloading, Panorama will either put it into a variable, a file, or both. This example loads the specified web page into a fileglobal variable named pageContents. (If the variable doesn’t exist, it will be created.)

 urltask("http://www.somesite.com/somepage.html","variable","pageContents")

This example saves the specified web page as a text file.

 urltask("http://www.somesite.com/somepage.html","file","~/Documents/Test/Page.txt")

Note: If you want, you can specify both a variable and a text file – Panorama will save the downloaded data into both. But you must specify at least one destination. If no destination is specified, the function will return an error and will not download the data in the url.

Note: You can abbreviate "variable" as "var". You can also use upper or lower case, for example "FILE" instead of "file".

Advanced: When saving the downloaded data into a variable, Panorama attempts to determine the type of data that has been downloaded. If it can positively determine that the data is text, the data will be stored into the variable as text. Otherwise, the data will be store in binary format. If you know the data is text, you can convert it with the binarytotext( function, and many functions and statements will also perform this conversion automatically, so in general you don’t have to worry about this.

Running Code After the Data is Downloaded

Suppose you want to display the data after it is downloaded. You might be tempted to do something like this:

fileglobal taskid,urldata
taskid = urltask("http://www.somesite.com/somepage.html","var","urldata")
displaydata urldata

However, this will not work. It may take some time for the data to be downloaded into the urldata variable, it could be seconds or even minutes. But the displaydata will execute immediately, even though the downloaded data isn’t ready yet. So you’ll either get an error message, or you’ll get whatever was previously left in the urldata variable.

To solve this, you can put code into the urltask( function itself.

fileglobal taskid,urldata
taskid = urltask("http://www.somesite.com/somepage.html",
    "var","urldata",
    "code",{displaydata urldata})

When Panorama finishes downloading the contents of the URL, it will automatically run the specified code. In this case, it means that a dialog will pop-up displaying the contents of the URL. This is actually a rather poor example, since you wouldn’t want a dialog to suddently pop-up out of nowhere. A more common application would be to set up a form with a Text Display object that displays the urldata object. This example will update the form to display the downloaded content when it becomes available.

fileglobal taskid,urldata
taskid = urltask("http://www.somesite.com/somepage.html",
    "var","urldata",
    "code",{showvariables urldata})

If the code contains the tag «taskid», Panorama will substitute the actual task ID into the code. This is for use with the waitfortask and resumeaftertask statements. Note: The «taskid» tag must be all lower case, and cannot contain any punctuation or spaces.

Internet Errors

In the examples given so far, Panorama would simply abort the download if an internet error occurred. There wouldn’t be any error message, and the code you have assigned to run at completion would not run. If you want to explicitly handle errors, start your code with the urltaskstatus statement, followed by if error. This example will display a notification if there is an error.

fileglobal taskid,urldata
taskid = urltask("http://www.somesite.com/somepage.html",
    "var","urldata",
    "code",{
        urltaskstatus
        if error
             nsnotify "Network Error","TEXT",info("error")
             rtn
        endif
        showvariables urldata
     })

Note: Only actual internet errors (for example, the network is down) are handled by this technique. A missing web page (404 error) is not an internet error. You have to manually check the received content for that type of error.

Displaying Progress

Depending on what resource is being accessed, it could take seconds or even minutes to download an item (for example a large PDF file) from the web. The urltask( function can be configured to automatically update variables indicating the progress of the download. These variables can be displayed on a form using a Text Display Object or a Progress Indicator Object.

This example creates a fileglobal variable named DownloadPercentage.

urltask("http://www.somesite.com/bigfatlong.pdf", ... ,"progress","DownloadPercentage")

As the download proceeds, this variable will gradually increase from 0 to 100. You can display this variable on a form using a Text Display Object or a Progress Indicator Object object.

If you want to display the exact details, you can also create variables that will contain the exact number of bytes downloaded, as well as the number of bytes expected.

urltask("http://www.somesite.com/bigfatlong.pdf", ... ,
    "progress","DownloadPercentage",
    "bytesreceived","DownloadBytes",
    "bytesexpected","DownloadTotal",
)

If the progress variable is being displayed in a Text List or Matrix object, you may need to force redisplay of a different variable to force the list or matrix to redraw. You can do this with the “progresssync” option, as shown below. This example assumes that there is a variable named CatalogList that contains some or all of the data for a list or matrix object. The urltask( function will not change the value of this variable, but it will force it to be redisplayed.

urltask("http://www.somesite.com/bigfatlong.pdf", ... ,
    "progress","DownloadPercentage",
    "progresssync","CatalogList"
)

If you do this, you must use fileglobalvalue( function to display the actual progress value within the list or matrix. You would probably want to generate a custom “progress” variable name for each download, then use fileglobalvalue( to display the proper progress in each matrix element. The Panorama Server Servers wizard does this to display the progress as databases are downloaded.

Displaying Progress in the Toolbar – Download progress can also be displayed in the toolbar banner by using the banner option, like this:

urltask("http://www.somesite.com/bigfatlong.pdf", ... ,
    "banner","YES"
)

To enable progress display in the banner, use "YES", "TRUE" or true(). You can also enable both progress display in the banner and progress display in a form using a variable at the same time.

Loading a resource with form data (HTTP POST)

So far, all of the examples shown have been for HTTP GET requests. You can also submit a POST request with one or more data items. To do this, create a dictionary with the items to be submitted, then pass this dictionary to the function using the post option.

fileglobal taskid,urldata
taskid = urltask("http://www.somesite.com/register",
    "var","urldata",
    "post",initializedictionary("Name","John Smith","Email","jsmith@xyzmail.com"))

User Authentication

If a web page requires a user name and password, use the USER option. The option value must be in the format username:password.

urltask("http://www.somesite/securepage","USER","johnsmith:secret")

If the user name or password is incorrect, an error will occur (see Internet Errors above).

HTTP PUT, DELETE, etc.

Most URLs are accessed via the GET or PUT HTTP methods, but you can submit a request with any type of HTTP request.

urltask("http://www.somesite.com/some/resource","METHOD","PUT", ... )

If you have no idea what PUT, DELETE etc. are you probably don’t need this option!

Cancelling a Task

Suppose you have created a task to download a big PDF file.

fileglobal taskid,urldata
taskid = urltask("http://www.somesite.com/bigfatlong.pdf",
    "file","~/User/Documents/bigfatlong.pdf")

This file may take a minute or two to download. To cancel this download before it finishes, use this procedure.

 urltaskcancel taskid

Note: If the task has already completed, this statement will result in an error. You can trap this with if error if you just want to punt.

Global, Database and Window Scope

If a download takes a long time the user may have completely changed the Panorama environment before the download is complete. They may have switched to a different window, opened new windows, or even closed the original window and/or databases. However, Panorama normally assumes that the download task is attached to the database that was active when the urltask( function was invoked. This is called database scope. If the data is being saved in a variable, that variable will be a fileglobal variable associated with that database. In addition, the completion code will run using a secret window associated with that database. (If the original database has closed, the download is abandoned and the completion code won’t run at all.)

There are actually three options for scope – database, window, and global. Use the scope option to specify which to use.

urltask(...,"scope","database",...)
urltask(...,"scope","window",...)
urltask(...,"scope","global",...)

If window scope is used, data will be saved to a windowglobal variable (unless of course it is saved to a file). The completion code will not run unless the original window is the front window – if it is not, it will wait. (If the original window is closed, the download is abandoned and the completion code won’t run at all.)

If global scope is used, data will be saved to a global variable (unless of course it is saved to a file). Note: You should not use global scope if you are displaying the progress of the download, this feature won’t work correctly for global scope.

Information about the Downloaded Item

The code that runs when the download is completed has the option of retrieving information about the downloaded item, including the MIME type, suggested filename, and text encoding (if any). To do this, the first statement in the code should be the urltaskstatus statement. Then at a later point, the code can use the info(“urltaskinfo”) function to get a dictionary that contains all of the available information about the download.

This example downloads an image into a file. The filename is not specified, only the folder, so the filename returned from the web server will be used. After the download is complete the image will be opened in the Preview application.

local siteurl,image
siteurl=...
imageurl=...
taskid = urltask(siteurl+image,
    "file","~/Pictures/WebStuff/",
    "code",{
        urltaskstatus
        local imagefile
        imagefile=getdictionaryvalue(info("urltaskinfo"),"FILENAME")
        openwith "Preview","~/Pictures/WebStuff/"+imagefile
    })

The information available from the urltaskstatus statement is:

MIME – Mime type of the returned data, for example text/plain, text/html, or image/jpg.

FILENAME – The filename suggested by the server for this content.

ENCODING – If the content is text, this is the encoding of the text, for example UTF-8. Note: This information is sometimes missing.

Accessing HTTP Header Information

In addition to information about the downloaded data, your completion code can also access information from the HTTP header that was returned with the item. To do this, the first statement in the code should be the urltaskstatus statement (just as in the previous section). Then at a later point, the code can use the info(“httpheaders”) function to get a dictionary that contains all of the available information from the header. The exact dictionary entries will vary depending on the server queried, but here is a typical example.

	Server=Apache/2.2.15 (Unix) mod_ssl/2.2.15 OpenSSL/0.9.8l PHP/5.3.3
	Connection=Keep-Alive
	Etag="4e6c5-b60f-4e4f0aea25200"
	Keep-Alive=timeout=15, max=499
	Content-Type=text/html
	X-Frame-Options=SameOrigin
	Expires=Thu, 09 Oct 2014 08:53:21 GMT
	Cache-Control=max-age=60
	Accept-Ranges=bytes
	Last-Modified=Tue, 27 Aug 2013 16:51:20 GMT
	Date=Thu, 09 Oct 2014 08:52:21 GMT
	MS-Author-Via=DAV
	Content-Length=46607

If you only need the header information and not the data itself, set the METHOD to HEAD. For example you might want to do this to verify that a resource exists without taking the time to download the whole thing.

Timeout

The urltask( function will normally wait for up to 60 seconds of network inactivity before giving up on a task. Use the timeout option to change this. This example changes the timeout to 10 seconds (in other words, if the network is unavailable for more than 10 seconds, *urltask(* will give up).

urltask(...,"timeout",10, ...)

You can also use the tasktimeout option to set an overall timeout for the entire task. The default timeout option is 10 minutes – in other words, if it takes more than 10 minutes to download the file, the urltask( function will give up even if the network is working (slowly). This example increases the timeout to an hour (for example if you were expecting to download something large on a slow network).

urltask(...,"tasktimeout",3600, ...)

Cache Policy

Use the cachepolicy option if you want non-standard cache handling. If you want to ignore the cache and always go to the server, set the cache policy to 1.

urltask(...,"cachepolicy",1, ...)

If you want to get hardcore and find out about other options, google NSURLRequestCachePolicy. For almost all operations, the default policy (0) is the way to go.

Keep Alive

Set the keepalive option to true if you want to keep the connection to the server open. You should only do this if you are planning to rapidly access the server over and over again. Make sure that on the last access to the server you set this option to false (or omit it, the option defaults to false if not specified), failing to do this will result in a memory leak (the memory won’t be reclaimed until Panorama is quit).

urltask(...,"keepalive",true(), ...)

See Also


History

VersionStatusNotes
10.2NewAdded the "progresssync" and "banner" options, see the "Displaying Progress" section above. Also now expands «taskid» in the code into the actual task id. Also the new "keepalive" option.
10.0NewNew in this version.