MagicPath (DOWNLOADFROMSTREAM and UPLOADINTOSTREAM without a dialog box)


The C/AL commands DOWNLOADFROMSTREAM and UPLOADINTOSTREAM have the purpose of sending files between RTC and the NAV Server. A few times now, we had the question: How can we use these functions without it displaying the dialog box to select a file and folder name?

This is how you can automatically download and upload files without any user interactions:

The trick is to use MagicPath, like in codeunit 419 "3-Tier Automation Mgt.". MagicPath is initiated by setting the folder name to '<TEMP>' like this:
DOWNLOADFROMSTREAM(IStream,'','<TEMP>', '',MagicPath);

 

DOWNLOADFROMSTREAM

The code example below will copy a specific file from the NAV Server to the RTC machine with no questions asked about folder or file name or anything else:


IF NOT ISSERVICETIER THEN
  EXIT;
FileToDownload := 'c:\Temp\ServerFile.txt';
FileVar.OPEN(FileToDownload);
FileVar.CREATEINSTREAM(IStream);
DOWNLOADFROMSTREAM(IStream,'','<TEMP>', '',MagicPath);
MESSAGE('Path = ' + MagicPath);

FileVar.CLOSE;

 

Variables:

Name Data Type Length
FileToDownload  Text 180
FileVar File
IStream  InStream
MagicPath  Text 180

 


Now we have the file on the RTC machine, and MagicPath tells us its location. The location will be something like this:
C:\Users\[UserName]\AppData\Local\Temp\Microsoft Dynamics NAV\4612\__TEMP__ff7c5a286cfd463f9f7d92ae5b4757e2

The number 4612 in the MagicPath comes from the Process ID of RTC.

 

Handling files client side

So, what if we wanted to rename it to a specific name? We have the FILE object in C/AL, but of course since C/AL runs on the NAV Server and not on RTC, this won't work since the purpose of the above is exactly to copy the file to the client machine. Instead, use this automation:

'Microsoft Scripting Runtime'.FileSystemObject

Then create an instance ClientSide:
CREATE(FileSystemObject,TRUE,TRUE);


So, if you wanted to continue the code above and place and name the file to something specific on the client's machine, add these lines:


CREATE(FileSystemObject,TRUE,TRUE);
DestinationFileName := 'c:\Temp\newfile.txt';
IF FileSystemObject.FileExists(DestinationFileName) THEN
  FileSystemObject.DeleteFile(DestinationFileName,TRUE);
FileSystemObject.CopyFile(MagicPath,DestinationFileName);
FileSystemObject.DeleteFile(magicpath,TRUE);

 

 
UPLOADINTOSTREAM


MagicPath works both ways. But with DOWNLOADFROMSTREAM it creates MagicPath for you and tells you where it is. With UPLOADINTOSTREAM you need to know it in advance. Remember the MagicPath location above includes the Process ID of RTC. One way could be to work that out somehow. But what I would suggest instead, is to download a temp test file first, then see where MagicPath downloads it to. The path for upload will be the same:


// download a temp file to get MagicPath
FileVar.CREATETEMPFILE;
FileVar.CREATEINSTREAM(IStream);
DOWNLOADFROMSTREAM(IStream,'','<TEMP>', '',MagicPath);
FileVar.CLOSE;
MESSAGE(MagicPath);


Then extract the folder name from MagicPath:

FOR i := STRLEN(MagicPath) DOWNTO 1 DO BEGIN
  IF MagicPath[i] = '\' THEN BEGIN
    MagicPath := COPYSTR(MagicPath,1,i);
    i := 1;
  END;
END;

Once you know the location of MagicPath, the next step is to copy the file you want to upload into that folder:

FileToUpload := 'newfile.txt';
FolderName := 'c:\Temp\';

IF ISCLEAR(FileSystemObject) THEN
  CREATE(FileSystemObject,TRUE,TRUE);
FileSystemObject.CopyFile(FolderName + '\' + FileToUpload,MagicPath + '\' + FileToUpload);

Then use UPLOADINTOSTREAM to upload the file from MagicPath to the NAV Server:
UPLOADINTOSTREAM('','<TEMP>','',FileToUpload,IStream);


And finally, save the InStream to a file on the server:

FileVar.WRITEMODE(TRUE);
FileVar.CREATE('c:\Temp\OnServer.txt');
FileVar.CREATEOUTSTREAM(OStream);
COPYSTREAM(ostream,istream);
FileVar.CLOSE;

 

So, put all this together and the end result is:

The file c:\Temp\ServerFile.txt gets downloaded to C:\Temp\NewFile.txt, and then uploaded back to the server as C:\Temp\OnServer.txt.

 

 

Lars Lohndorf-Larsen

Dynamics NAV Support EMEA

 

 

 

 

 

Comments (9)

  1. Sundari says:

    This code works very well! Thanks!

  2. Tommy says:

    Awesome. Very nice.

    But how do I upload to a "temporary" place on the servicetier. I can easily get a temporary file created on the client. But how do I go about doing the same on the ServiceTier? In CU 419: ServerTempFilename looks like a function that would do just that. But it just creates a temporary file on the client. Not the server.

  3. Tommy says:

    Nevermind. Always helps to ask someone.

    Just do like this:

    File.CREATE(FileSystemObject.GetTempName);

    and FILE.NAME will return the fine new temporary file just created on the servicetier.

  4. chris says:

    Looks unnecessary "complicated" to me :). Why not adding a bool parameter like "HideDialog" to the downloadfromstream method to prevent the dialog from opening. If true the file is saved to the given path and filename.

  5. Heino says:

    This was (almost) completely what I was looking for 🙂 But what if you don't know the exact filename(s) on the file(s)? For example if you want to handle all the files in a specified folder (one file at a time). In the Classic client you would use the File record, but how do you do it from RTC?

    Thanks.

  6. Peter says:

    @Heino: You will need to use an Automation Server 🙁 Get inspiration from the example from Mark here: http://www.mibuso.com/…/viewtopic.php

  7. Scott says:

    Thank you,

    This article helped me fix standard NAV2009 interactions on 3-Tier so don't get file dialag box's all time. Still not sure why cannot use UNC's for file storeage location other than to local shares on middle tier, the last place client wants to store all interactions and attachments is on middle tier server so ideally should be able to write to file shares on NAS or other servers.

    Keep up the good work!

  8. jbellinger@norcompcorp.com says:

    I occasionally get a message;

    'This message is for C/AL programmers:  The call to member DeleteFile failed: Exception from HRESULT: 0x800A0035 (CTL_EFileNOTFOUND).'

    Suggestions?

  9. NAV learner says:

    Hi everyone,

    if the user running the code (e.g. for the UPLOADINTOSTREAM ) from the UI hasn't any read or write permissions in the server folder (of course the server path is known) does the code still works?

    Kind Regards

Skip to main content