UPLOAD and DOWNLOAD size limit

Always something new.  I have bin using the Record Links to store pointers to scanned files, created pdf files all other files that the user would like to link to a record and store centrally.  I have the option to import the file to a BLOB field and also to a separate tables in a different database.

What I do next is to install a single aspx page to an internal web server and the URL in the Record Links table points me to this page with parameters that define where to get the centrally stored file.  This aspx page can fetch the file from the database or through web services from NAV BLOB field.

My first version of this was to have everything executed on the client side.  I did not see that working for NAV 2013 where we can have users that authenticate outside the windows domain.  The same is for NAV 2009 R2 where the Role Tailored Client is connecting to the service tier via WAN.

So I moved the functionality to the service tier and wanted to use UPLOAD and DOWNLOAD to transfer the files to and from the client.  Here I hit a wall.  There is a size limit to the files that I can upload and download.

I therefore looked at the code I had created earlier and modified it a little bit.

[code]PROCEDURE UploadClientFile@1100408005(FileName@1100408000 : Text[1024]) ServerFileName : Text[1024];
VAR
Document@1100408011 : BigText;
ServerConvert@1100408010 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.Convert";
ServerBase64File@1100408009 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.File";
ServerDocumentFile@1100408008 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.File";
ClientConvert@1100408007 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.Convert" RUNONCLIENT;
ClientFile@1100408006 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.File" RUNONCLIENT;
ServerFileStream@1100408005 : File;
ServerBase64FileName@1100408004 : Text[1024];
OutStr@1100408002 : OutStream;
BEGIN
Document.ADDTEXT(ClientConvert.ToBase64String(ClientFile.ReadAllBytes(FileName)));
ServerBase64FileName := ThreeTier.ServerTempFileName(”,”);
ServerFileStream.WRITEMODE(TRUE);
ServerFileStream.CREATE(ServerBase64FileName);
ServerFileStream.CREATEOUTSTREAM(OutStr);
Document.WRITE(OutStr);
ServerFileStream.CLOSE;

ServerFileName := ThreeTier.ServerTempFileName(”,”);

ServerDocumentFile.WriteAllBytes(
ServerFileName,
ServerConvert.FromBase64String(
ServerBase64File.ReadAllText(ServerBase64FileName)));

ServerBase64File.Delete(ServerBase64FileName);
END;

PROCEDURE DownloadServerFile@1100408017(FileName@1100408000 : Text[1024]) ClientFileName : Text[1024];
VAR
Document@1100408002 : BigText;
ServerFile@1100408003 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.File";
ServerConvert@1100408001 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.Convert";
ClientBase64File@1100408006 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.File" RUNONCLIENT;
ClientStreamWriter@1100408007 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.StreamWriter" RUNONCLIENT;
ClientConvert@1100408010 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.Convert" RUNONCLIENT;
ClientFile@1100408009 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.File" RUNONCLIENT;
ClientPath@1100408011 : DotNet "’mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′.System.IO.Path" RUNONCLIENT;
ClientBase64FileName@1100408008 : Text[1024];
SubString@1100408004 : Text[1024];
Pos@1100408005 : Integer;
BEGIN
Document.ADDTEXT(ServerConvert.ToBase64String(ServerFile.ReadAllBytes(FileName)));
ClientBase64FileName := ThreeTier.ClientTempFileName(”,’b64′);
ClientStreamWriter := ClientBase64File.CreateText(ClientBase64FileName);
Pos := 1;
WHILE Pos < Document.LENGTH DO BEGIN
Pos := Pos + Document.GETSUBTEXT(SubString,Pos,MAXSTRLEN(SubString));
ClientStreamWriter.Write(SubString);
END;
ClientStreamWriter.Close;

ClientFileName :=
ClientPath.GetTempPath +
SigningTools.RemovePath(FileName);

ClientFile.WriteAllBytes(
ClientFileName,
ClientConvert.FromBase64String(
ClientBase64File.ReadAllText(ClientBase64FileName)));
END;
[/code]

The problem is that this method is not fast enough. Perhaps someone reading this has a faster solution.  I convert the file to base64 and use BigText variable to move it from and to the service tier.  This will support large files but it is slow.

Copy Record Link between databases

In my current upgrade process I needed to copy the Record Link table from one database to another.  I can use a copy-paste method for small number of records but in this case I needed something else.

A Dataport or a XML Port was the way I choose to go.  There is one problem though.  the Record Link table has a field for the Record ID and this field is not a field type that can be used in dataports or xml ports.

I created two new global variables, one text variable for the record position and one integer variable for the table number.  And to help me with the conversion I needed to have two more global variables; RecID  and RecRef.

RecordLinkVariables

Now for the code.  To convert my Record ID field to a record position and a table number

RecordLinksBeforeExport

and to convert from the table number and position to a Record ID

RecordLinksAfterImport

Client Beep

In the Classic Client we had the C/AL command BEEP to sound an alert to the user.  This function is not supported in the Role Tailored Client.

Here we have a solution in .NET.

[code]IF ISSERVICETIER THEN
Console.Beep
ELSE
BEEP(1000,300);[/code]

Where Console is a RunOnClient DotNet variable ‘mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’.System.Console

Customer Statistics FactBox

The Page 9082 is not displaying correct information.  One of the fact boxes for sales is the Customer Statistics factbox page 9082.

origpage9082

The last amount, “Sales YTD (LCY):” is in fact the total sales for the customer.  I wanted to change this and use 12 months sales instead of YTD sales.  I changed the caption according to that and changed the code.

[code]
OnAfterGetRecord()

IF CurrentDate <> WORKDATE THEN BEGIN
CurrentDate := WORKDATE;
END;

SETRANGE("Date Filter",0D,CurrentDate);
CALCFIELDS(
Balance,"Balance (LCY)","Balance Due","Balance Due (LCY)",
"Outstanding Orders (LCY)","Shipped Not Invoiced (LCY)");

TotalAmountLCY := "Balance (LCY)" + "Outstanding Orders (LCY)" + "Shipped Not Invoiced (LCY)" + "Outstanding Invoices (LCY)";

SETRANGE("Date Filter",CALCDATE(”,CurrentDate),CurrentDate); //#01-

CALCFIELDS(
"Sales (LCY)","Profit (LCY)","Inv. Discounts (LCY)","Inv. Amounts (LCY)","Pmt. Discounts (LCY)",
"Pmt. Disc. Tolerance (LCY)","Pmt. Tolerance (LCY)",
"Fin. Charge Memo Amounts (LCY)","Cr. Memo Amounts (LCY)","Payments (LCY)",
"Reminder Amounts (LCY)","Refunds (LCY)","Other Amounts (LCY)");
SETRANGE("Date Filter",0D,CurrentDate);[/code]

where the line

SETRANGE(“Date Filter”,CALCDATE(‘<-12M>’,CurrentDate),CurrentDate); //#01-

is added.