Downloading Files

In Authoring and Projectors, it is possible to download files using the downloadNetthing Lingo function (this is not available in Shockwave). It works much like the other network lingo functions discussed earlier: starting a network download returns a NetID. You can then monitor the progress of the download.

Here is an example class (script) for managing downloads. It works in a similar way to the other 'netOp' classes available at the LingoWorkshop. Here is some lingo to create an instance of the script and tell it to start downloading the file, making some callbacks to keep us informed of the download progress:

NetOp = script("NetOp.download").new(UpdateURL, localFileName)

NetOp.AddListener (me)

NetOp.Start()

The first line creates a new instance of the script, and specifies the download url and a local file name. The next line adds the current script as a 'listener' (an object the NetOp should send messages to). The third line actually starts the download. When the download is complete, the NetOp will send a DownLoadComplete message to the listener objects.

Downloading multiple files

It is possible to download more than one file at a time. Director will start queuing downloads if you try and initiate too many at once (the network status will be 'connecting...') and multiple concurrent connections might slow down the individual connection. Running 2,3 or even 4 downloads at once seems to be acceptable.

Here is an example script for downloading multiple files. The main method of this script looks like this:

on FetchFiles (me, listOfURLS, directoryToSaveFiles)

  if NOT xtraP("NetLingo") then \

     return "Error - NetLingo Xtra is missing" 

  if NOT listP(listOfURLS) then \

     return "Bad parameter (list of urls is not a list)"

  if NOT folderExists(directoryToSaveFiles) then \

     return "Bad parameter (local folder does not exist)"

  

  UpdateList = listOfURLS

  DownloadDir = directoryToSaveFiles

  if (the last char of DownloadDir <> the last char of the moviePath) then

    DownloadDir = DownloadDir & the last char of the moviePath

  end if

  SuccessCnt = 0

  FileCnt = count(listOfURLS)

  me._GetNextUpdate()

  return "OK"

end

The first three lines simply do some error checking (making sure that the NetLingo Xtra is available and that the parameters are ok). If everything looks good, it calls the _GetNextUpdate method which looks like this:

on _GetNextUpdate (me)

  

  if count(UpdateList) then

    

    if count(CurrentConnnections) < MaxConnections then 

      

      Updating = 1

      f = UpdateList[1]

      localFileName = DownloadDir & basename(f, "/")

      UpdateURL = f &"?v="&random(the milliseconds)

      

      me._UpdateStatus("Fetching file: " & UpdateURL, UpdateURL)

      UpdateList.deleteAt(1)

      

      NetOp = script("NetOp.download").new(UpdateURL, localFileName)

      NetOp.AddListener (me)

      NetOp.SetCallback(#DownloadComplete, #DownloadComplete)

      NetOp.SetCallback(#DownloadStatusUpdate, #DownloadStatus)

      NetOp.Start()

      CurrentConnnections.append(NetOp)

      me._GetNextUpdate()

      

    else

      

      -- need to wait for one of the current operations to finish

      -- and call _GetNextUpdate

      

    end if

    

  else

    if count(CurrentConnnections) = 0 then

      me._UpdateStatus("")

      Updating = false

      me._UpdateStatus("Finished downloading files. \

	  Successfully downloaded " &SuccessCnt&" out of "&FileCnt&" files.")

      call(#FetchFilesComplete, Listeners)

    end if

  end if

  

end

Basically, each time the _GetNextUpdate method is called, it checks whether there is less than the allowed number of connections still active, and if there is, it creates a new download object. Each time a download object is created, the url of the thing being downloaded is sliced off the list. When a download object finishes, it sends a downloadcomplete message back to this script. The download method looks like this:

on DownloadComplete (me, op, args)

  CurrentConnnections.deleteOne(op)

  if args.ilk = #PropList then 

    if args.error = 0 or args.error = 4816 then 

      -- got the file

      if FileExists(args.localAddress) then

        me._UpdateStatus("File downloaded.", args.remoteaddress)

      end if

      SuccessCnt = SuccessCnt + 1

    else

      -- some error handling code here

    end if

  else

    -- some error handling code here

  end if

  me._GetNextUpdate()

end

Here is a demo movie (DIR file) - includes demo of ProxyHelper script (see below)

Dealing with firewalls and other impediments

One problem with downloading files from a projector is getting through firewalls and other devices designed to stop software from downloading things. Director has a lingo function for configuring proxy settings used by the projector which can work. You can either ask your users to provide their proxy address and port number, or use this script and attempt to read their settings from the registry and do it all automatically. Otherwise, you could use an Xtra such as SecureNet from INM (you might have to use an Xtra if the proxy requires a username and password).

Some other issues

I've noticed (so far only on an OSX system running the Apache server) that some files simply refuse to download. Director says there is an error 4165 (bad url) - but the file can be downloaded using a web browser. It might have something to do with the path name or permissions.

First published 28/07/2006