Time is flying! My last post is already more then four months ago, so it’s high time to post a new one.
Last week I was struggling with the UPLOAD statement. First of all, I always need some twisted thinking here: the code is running on the Service Tier, but DOWNLOAD doesn’t mean that you download a file to the server. And UPLOAD doesn’t mean that your code on the server will send a file to the Role Tailored Client. The opposite is true: it seems that these two statements are executed by the client instead of the server. Or at least you should think that way…
Ok, so DOWNLOAD means that you want to send a file from the server to the client while UPLOAD sends a file the other way.
The case that I was trying to solve, was to send a known file from the RTC to the Service Tier. Our customer wanted to attach a file (or complete folder) to an email. The email setup was to use SMTP and not Outlook integration.
The problem in this case is that SMTP Mail Codeunit runs on the Service Tier, while the file or folder setup was done via the RTC. So the user picked a folder that was local to the client and not available to the server.
No problem… we can UPLOAD the file(s), without showing any dialog box…., I thought…
We all know Codeunit 419 3-Tier Automation Mgt., which can be used for handling files between RTC and Service Tier. So I looked into this Codeunit to find the function that accepts a local file path on the client, upload it to the server and returns the server path. And I noticed that such a function is not available. Hmmm….
So I wrote my own UploadFile function in Codeunit 419 that does a silent upload to the Service Tier, which I want to share with you.
Variables:
Name | DataType | Subtype | Length |
ServerFileName | Text | 1024 | |
FileInfo | DotNet | ‘mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’.System.IO.FileInfo |
FileInfo should have property RunOnClient = Yes.
[codesyntax lang=”progress” title=”UploadFile”]
UploadFile(ClientFileName : Text[1024]) : Text[1024] FileInfo := FileInfo.FileInfo(ClientFileName); ClientTempFileName(FileInfo.Name,FileInfo.Extension); IF FileInfo.DirectoryName + '\' <> ClientTempPath THEN FileInfo.CopyTo(ClientTempPath + FileInfo.Name); UPLOAD('',Magicpath,'',FileInfo.Name,ServerFileName); EXIT(ServerFileName);
[/codesyntax]
The trick to avoid the dialog box, is to use the Magicpath (which is simply the text ‘<TEMP>’) for the FromFolder parameter. This means that the RTC expects the file to exist in the RTC temp folder. Don’t use the UPLOAD statement with the Magicpath when the file is not existing in the RTC temp folder! It will throw an error on the server and the RTC connection with the Service Tier will be lost.
The steps that need to be done are:
- Find the RTC temp folder (a function is available in Codeunit 419)
- Check if the file is in the temp folder. If not, copy it to the temp folder
- Upload the file from the temp folder to the server
- Return the server path
I my eyes the UPLOAD function could use some improvements. Things that came to my mind:
The dialog box can be suppressed by using <TEMP> in the FromFolder parameter. However, then the file must also exist in the client temp folder. Why isn’t there an extra parameter ShowDialog? Than you can control the dialog and still have the option to upload a file from any location, whithout the need to copy it first to the client temp folder.
To find the RTC temp folder, the function ClientTempFileName first creates a temporary file on the server, then downloads it to the client and finds the path from the downloaded file. Wow, that’s making things complex! Why isn’t a global variable CLIENTTEMPPATH available?
Suggestions are posted to Connect. You can vote for it here: https://connect.microsoft.com/dynamicssuggestions/feedback/details/727910/improvements-for-upload-and-download-statement
Anyway, this code snippet makes life a little bit easier.
Thanx, AJ.
Please consider to put your inprovement siggestion to UPLOAD to msconnect. If you do, let us know so we can vote for it.
b rg
Luc
Hi Luc,
Thanks for suggestion, I was a little bit hesitating if it is worth to send to Connect.
I have posted it now, see the link above.
Gr,
Arend-Jan
Was solved by new functions in NAV 2013: UploadFileSilent and UploadFile.
Did you check this blog..is it helpfull in this case?
http://mibuso.com/blogs/mohana/page/2/
No, I wasn’t aware of that blog. Probably it didn’t show up in the search (maybe due to my search criteria).
However, when blogging it is inevitable that you sometimes post an article about the some topic that was already covered by another blogger.
expedient view site…
Try create this method insteader.. much easier
VARIABLES:
Name DataType Subtype Length
ClientFilePathL Text 1024
FileNameL Text 1024
ServerFilename Text 1024
i Integer
SilentUploadFileToServer(ClientFileNameL : Text[1024]) : Text[1024]
FOR i := STRLEN(ClientFileNameL) DOWNTO 1 DO BEGIN
IF (COPYSTR(ClientFileNameL,i,1) = ‘\’) AND (ClientFilePathL = ”) THEN BEGIN
ClientFilePathL := COPYSTR(ClientFileNameL,1,i-1);
FileNameL := COPYSTR(ClientFileNameL,i+1);
END;
IF UPLOAD(”,MagicPath,”,FileNameL,ServerFilename) THEN
EXIT(ServerFilename);
END;
EXIT(”);
Hello AJK,
I a getting error like
Microsoft Dynamics NAV
—————————
This message is for C/AL programmers: The call to member CopyTo failed: Could not find file ‘C:\RM\Tosend\ACH-02112014\RM1650 021114 080457’..
—————————
OK
—————————
It seems like CopyTo method unable to read files from my RM folder.
Please suggest me..
We have 3-tiers on 3 machines installed.
Can I use this logic on webclient as I have doubt this solution would not work on webclient because of dotnet datatype
Now, this is not available for the webclient. Codeunit 419 File Management has functions to silently upload files, but those won’t work with BC SaaS. However, they may work for the webclient on-prem, haven’t tried that out.
thanks for your reply but with SilentUpload Function it gives the error of .Net Interop.
You are right, it fails because it’s not possible to run .Net on the client.
So the only option to silently upload files would be to use a cloud storage that automatically synchronizes local files. E.g. OneDrive, SharePoint, Dropbox, even some FTP servers do offer that. And then automatically read those files from the cloud storage, for which I recommend to use Microsoft Flow in combination with API’s.