{"id":183,"date":"2019-11-28T11:59:22","date_gmt":"2019-11-28T10:59:22","guid":{"rendered":"https:\/\/lessto.dk\/cloudtofile\/?page_id=183"},"modified":"2019-12-13T21:00:19","modified_gmt":"2019-12-13T20:00:19","slug":"lessto-bc365-spring-code-example-eng","status":"publish","type":"page","link":"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-spring-code-example-eng\/","title":{"rendered":"lessto &#8211; BC365 spring &#8211; code &#8211; example &#8211; eng"},"content":{"rendered":"<h1><span style=\"font-family: Impact, Charcoal, sans-serif; font-size: 40px; color: rgba(54, 162, 235, 0.8);\">lessto CloudToFile<\/span><\/h1>\n<p>Demo of Business Central 365 spring edition (14) where data is transferred to and from a FTP site. A simple cloud to file function.<\/p>\n<p><a href=\"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-wave-2-code-example-eng\/\">Code for Business Central 365 Wave 2 (15)<\/a><br \/>\n<a href=\"https:\/\/lessto.dk\/cloudtofile\/lessto-ftp-com\/\">Simpel demo of the four FTP commands<\/a><br \/>\n<a href=\"https:\/\/lessto.dk\/cloudtofile\/lessto-cloudtofile-wordpress-php-example\/\">The full wordpress code from the demo.<\/a><\/p>\n<p>The code works both in local installation, server onprem, docker and cloud version.<\/p>\n<p>The first page extenstions are for demo purpose, use the code to make your own AL code.<\/p>\n<p>The codeunit is what makes the magic happens, so do not make changes.<\/p>\n<p>Feel free to use the code if you have projects with http request, JSON conversion and BASE64.<\/p>\n<p>The keypoints is to change the APIKEY and ftp information, this can be done in the AL code. In customer code it should be saved in a table.<\/p>\n<p>The next keypoint is to make the call to the codeunit.<\/p>\n<p>lesstoFTPmanagement.lesstoFTPsend(apikey, ftpuser, ftppassword, ftpserver, ftpdir, ftpfilename, base64, errorno, errortext, status, serverfile);<\/p>\n<p>You can make this call in pages and codeunits and batchjobs.<\/p>\n<p>Here is the code. You could make the codeunit as one extension and the page extensions as another. After installation the actions are on the customer list-&gt;processing.<\/p>\n<pre>\r\npageextension 50000 lesstoFTPhttps extends \"Customer List\"\r\n{\r\nactions\r\n{\r\naddlast(Processing)\r\n{\r\nAction(FTPsendFile)\r\n{\r\nApplicationArea = Basic, Suite;\r\nimage = GetEntries;\r\nCaption = 'FTPsendfile';\r\nPromoted = true;\r\nPromotedCategory = Process;\r\nPromotedIsBig = true;\r\ntrigger OnAction();\r\nvar\r\napikey: Text[100];\r\nftpuser: Text[20];\r\nftppassword: Text[20];\r\nftpserver: Text[20];\r\nftpdir: Text[100];\r\nftpfilename: Text[50];\r\nbase64: text;\r\nlesstoFTPmanagement: codeunit \"lesstoFTPmanagement\";\r\n\r\nCustomer: Record Customer;\r\nFileBlob: Record Tempblob temporary;\r\nDataString: Text;\r\nFileOutStream: OutStream;\r\nFileInStream: InStream;\r\nCRLF: text[2];\r\nErrorno: Text[2];\r\nErrortext: Text[100];\r\nStatus: Text[100];\r\nServerfile: Text[200];\r\nbegin\r\n\r\napikey := '&lt;Your API key from lessto Cloud To File&gt;';\r\nftpuser := '&lt;FTP server user name&gt;';\r\nftppassword := '&lt;FTP server user password&gt;';\r\nftpserver := '&lt;FTP server name&gt;';\r\nftpdir := '&lt;FTP server directory&gt;';\r\nftpfilename := 'testcsvfile.csv'; \/\/ filename in this demo\r\n\r\nCRLF := ' ';\r\nCRLF[1] := 13;\r\nCRLF[2] := 10;\r\n\r\nFileBlob.Blob.CreateOutStream(FileOutStream, TextEncoding::UTF8);\r\nif customer.findfirst then\r\nrepeat\r\ndatastring := '\"' + customer.\"No.\" + '\",\"' + customer.Name + '\"' + CRLF;\r\nFileOutStream.WriteText(datastring);\r\nuntil customer.next = 0;\r\n\r\nbase64 := fileblob.ToBase64String();\r\n\r\nlesstoFTPmanagement.lesstoFTPsend(apikey, ftpuser, ftppassword, ftpserver, ftpdir, ftpfilename, base64, errorno, errortext, status, serverfile);\r\n\r\nif errorno &lt;&gt; '' then begin\r\nmessage('Errorno = ' + errorno + ' Errortext = ' + errortext);\r\nexit;\r\nend;\r\n\r\nmessage(status);\r\n\r\nend;\r\n}\r\n\r\nAction(FTPgetdir)\r\n{\r\nApplicationArea = Basic, Suite;\r\nimage = GetEntries;\r\nCaption = 'FTPgetdir';\r\nPromoted = true;\r\nPromotedCategory = Process;\r\nPromotedIsBig = true;\r\ntrigger OnAction();\r\nvar\r\napikey: Text[100];\r\nftpuser: Text[20];\r\nftppassword: Text[20];\r\nftpserver: Text[20];\r\nftpdir: Text[100];\r\nlesstoFTPmanagement: codeunit \"lesstoFTPmanagement\";\r\nErrorno: Text[2];\r\nErrortext: Text[100];\r\nStatus: Text[100];\r\ndirlist: array[1000] of text[100];\r\ni: integer;\r\ndirentry: text;\r\nCRLF: text[2];\r\nServerfile: Text[200];\r\nbegin\r\n\r\napikey := '&lt;Your API key from lessto Cloud To File&gt;';\r\nftpuser := '&lt;FTP server user name&gt;';\r\nftppassword := '&lt;FTP server user password&gt;';\r\nftpserver := '&lt;FTP server name&gt;';\r\nftpdir := '&lt;FTP server directory&gt;';\r\n\r\nCRLF := ' ';\r\nCRLF[1] := 13;\r\nCRLF[2] := 10;\r\n\r\nlesstoFTPmanagement.lesstoFTPgetdir(apikey, ftpuser, ftppassword, ftpserver, ftpdir, errorno, errortext, status, dirlist, serverfile);\r\n\r\nif errorno &lt;&gt; '' then begin\r\nmessage('Errorno = ' + errorno + ' Errortext = ' + errortext);\r\nexit;\r\nend;\r\n\r\nfor i := 1 to arraylen(dirlist) do begin\r\nif dirlist[i] &lt;&gt; '' then\r\ndirentry := direntry + dirlist[i] + CRLF;\r\nend;\r\n\r\nmessage(direntry);\r\n\r\nend;\r\n}\r\n\r\nAction(FTPgetfile)\r\n{\r\nApplicationArea = Basic, Suite;\r\nimage = GetEntries;\r\nCaption = 'FTPgetfile';\r\nPromoted = true;\r\nPromotedCategory = Process;\r\nPromotedIsBig = true;\r\ntrigger OnAction();\r\nvar\r\napikey: Text[100];\r\nftpuser: Text[20];\r\nftppassword: Text[20];\r\nftpserver: Text[20];\r\nftpdir: Text[100];\r\nftpfilename: Text[100];\r\nTextfile: Text;\r\nlesstoFTPmanagement: codeunit \"lesstoFTPmanagement\";\r\nErrorno: Text[2];\r\nErrortext: Text[100];\r\nStatus: Text[100];\r\ndirlist: array[1000] of text[100];\r\ni: integer;\r\ndirentry: text;\r\nCRLF: text[2];\r\nServerfile: Text[200];\r\nbegin\r\n\r\napikey := '&lt;Your API key from lessto Cloud To File&gt;';\r\nftpuser := '&lt;FTP server user name&gt;';\r\nftppassword := '&lt;FTP server user password&gt;';\r\nftpserver := '&lt;FTP server name&gt;';\r\nftpdir := '&lt;FTP server directory&gt;';\r\nftpfilename := 'testcsvfile.csv'; \/\/ filename in this demo\r\n\r\nCRLF := ' ';\r\nCRLF[1] := 13;\r\nCRLF[2] := 10;\r\n\r\nlesstoFTPmanagement.lesstoFTPget(apikey, ftpuser, ftppassword, ftpserver, ftpdir, ftpfilename, textfile, errorno, errortext, status, Serverfile);\r\n\r\nif errorno &lt;&gt; '' then begin\r\nmessage('Errorno = ' + errorno + ' Errortext = ' + errortext);\r\nexit;\r\nend;\r\n\r\nmessage(textfile);\r\n\r\nend;\r\n}\r\n\r\nAction(FTPdeletefile)\r\n{\r\nApplicationArea = Basic, Suite;\r\nimage = GetEntries;\r\nCaption = 'FTPdeletefile';\r\nPromoted = true;\r\nPromotedCategory = Process;\r\nPromotedIsBig = true;\r\ntrigger OnAction();\r\nvar\r\napikey: Text[100];\r\nftpuser: Text[20];\r\nftppassword: Text[20];\r\nftpserver: Text[20];\r\nftpdir: Text[100];\r\nftpfilename: Text[100];\r\nTextfile: Text;\r\nlesstoFTPmanagement: codeunit \"lesstoFTPmanagement\";\r\nErrorno: Text[2];\r\nErrortext: Text[100];\r\nStatus: Text[100];\r\nServerfile: Text[200];\r\n\r\nbegin\r\n\r\napikey := '&lt;Your API key from lessto Cloud To File&gt;';\r\nftpuser := '&lt;FTP server user name&gt;';\r\nftppassword := '&lt;FTP server user password&gt;';\r\nftpserver := '&lt;FTP server name&gt;';\r\nftpdir := '&lt;FTP server directory&gt;';\r\nftpfilename := 'testcsvfile.csv'; \/\/ filename in this demo\r\n\r\nlesstoFTPmanagement.lesstoFTPdelete(apikey, ftpuser, ftppassword, ftpserver, ftpdir, ftpfilename, errorno, errortext, status, serverfile);\r\n\r\nif errorno &lt;&gt; '' then begin\r\nmessage('Errorno = ' + errorno + ' Errortext = ' + errortext);\r\nexit;\r\nend;\r\n\r\nmessage(status);\r\n\r\nend;\r\n}\r\n}\r\n}\r\n}\r\ncodeunit 50000 \"lesstoFTPmanagement\"\r\n\r\n{\r\ntrigger OnRun()\r\nvar\r\n\r\nbegin\r\n\r\nend;\r\n\r\nprocedure lesstoFTPgetdir(apikey: Text[100]; ftpuser: Text[20]; ftppassword: Text[20]; ftpserver: Text[20]; ftpdir: Text[100]; var errorno: text[2]; var errortext: text[100]; var status: text[100]; var dirlist: array[1000] of text[100]; var serverfile: text[200]);\r\n\r\nvar\r\nTempBlob: Record TempBlob temporary;\r\nJsonResArray: JsonArray;\r\nJsonResToken: JsonToken;\r\nJsonResObject: JsonObject;\r\nhttploadOutStream: OutStream;\r\nhttploadInStream: InStream;\r\nContent: HttpContent;\r\nContentHeaders: HttpHeaders;\r\nClient: HttpClient;\r\nRequest: HttpRequestMessage;\r\nResponse: HttpResponseMessage;\r\nResponseText: text;\r\nPostString: Text;\r\ni: Integer;\r\nj: Integer;\r\nmaxi: integer;\r\nKeystring: text;\r\n\r\nbegin\r\n\r\nContent.GetHeaders(ContentHeaders);\r\nContentHeaders.Clear();\r\nContentHeaders.Add('Content-Type', 'application\/x-www-form-urlencoded; charset=UTF-8');\r\nTempBlob.Blob.CreateOutStream(httploadOutStream, TextEncoding::UTF8);\r\n\r\npoststring := '&amp;action=list' +\r\n'&amp;apikey=' + apikey +\r\n'&amp;user=' + ftpuser +\r\n'&amp;pass=' + ftppassword +\r\n'&amp;ftpserver=' + ftpserver +\r\n'&amp;ftpdir=' + ftpdir;\r\n\r\nhttploadOutStream.WriteText(poststring);\r\n\r\nTempBlob.Blob.CreateInStream(httploadInStream, TextEncoding::UTF8);\r\nContent.WriteFrom(httploadInStream);\r\nRequest.Content := Content;\r\nRequest.SetRequestUri('https:\/\/lessto.dk\/cloudtofile\/lessto-ftp-connect');\r\nRequest.Method := 'POST';\r\n\r\nClient.Send(Request, Response);\r\n\r\nResponse.Content().ReadAs(ResponseText);\r\n\r\nResponseText := '[' + ResponseText + ']';\r\nif not JsonResArray.ReadFrom((ResponseText)) then begin\r\nerrorno := '99';\r\nerrortext := 'Connection error';\r\nexit;\r\nend;\r\n\r\nFor i := 0 to jsonresarray.count - 1 do begin\r\njsonResarray.get(i, jsonrestoken);\r\nJsonResObject := jsonrestoken.asobject;\r\nend;\r\n\r\nif jsonresobject.get('errorno', JsonResToken) then\r\nerrorno := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('errortext', JsonResToken) then\r\nerrortext := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('status', JsonResToken) then\r\nstatus := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('serverfile', JsonResToken) then\r\nserverfile := jsonrestoken.asvalue.astext;\r\n\r\nmaxi := 1000;\r\n\r\nj := 0;\r\nFor i := 0 to maxi do begin\r\nKeystring := 'file' + format(i);\r\nif jsonresobject.get(Keystring, JsonResToken) then begin\r\nj := j + 1;\r\ndirlist[j] := jsonrestoken.asvalue.astext;\r\nend;\r\nend;\r\nend;\r\n\r\nprocedure lesstoFTPsend(apikey: Text[100]; ftpuser: Text[20]; ftppassword: Text[20]; ftpserver: Text[20]; ftpdir: Text[100]; ftpfilename: Text[50]; base64: text; var errorno: text[2]; var errortext: text[100]; var status: text[100]; var serverfile: text[200]);\r\nvar\r\nTempBlob: Record TempBlob temporary;\r\nJsonResArray: JsonArray;\r\nJsonResToken: JsonToken;\r\nJsonResObject: JsonObject;\r\nhttploadOutStream: OutStream;\r\nhttploadInStream: InStream;\r\nContent: HttpContent;\r\nContentHeaders: HttpHeaders;\r\nClient: HttpClient;\r\nRequest: HttpRequestMessage;\r\nResponse: HttpResponseMessage;\r\nResponseText: text;\r\nPostString: Text;\r\ni: Integer;\r\n\r\nbegin\r\n\r\nContent.GetHeaders(ContentHeaders);\r\nContentHeaders.Clear();\r\nContentHeaders.Add('Content-Type', 'application\/x-www-form-urlencoded; charset=UTF-8');\r\nTempBlob.Blob.CreateOutStream(httploadOutStream, TextEncoding::UTF8);\r\n\r\npoststring := '&amp;action=send' +\r\n'&amp;apikey=' + apikey +\r\n'&amp;user=' + ftpuser +\r\n'&amp;pass=' + ftppassword +\r\n'&amp;ftpserver=' + ftpserver +\r\n'&amp;ftpdir=' + ftpdir +\r\n'&amp;ftpfilename=' + ftpfilename +\r\n'&amp;base64=' + base64;\r\n\r\nhttploadOutStream.WriteText(poststring);\r\n\r\nTempBlob.Blob.CreateInStream(httploadInStream, TextEncoding::UTF8);\r\nContent.WriteFrom(httploadInStream);\r\nRequest.Content := Content;\r\nRequest.SetRequestUri('https:\/\/lessto.dk\/cloudtofile\/lessto-ftp-connect');\r\nRequest.Method := 'POST';\r\n\r\nClient.Send(Request, Response);\r\n\r\nResponse.Content().ReadAs(ResponseText);\r\n\r\nResponseText := '[' + ResponseText + ']';\r\nif not JsonResArray.ReadFrom((ResponseText)) then begin\r\nerrorno := '99';\r\nerrortext := 'Connection error';\r\nexit;\r\nend;\r\n\r\nFor i := 0 to jsonresarray.count - 1 do begin\r\njsonResarray.get(i, jsonrestoken);\r\nJsonResObject := jsonrestoken.asobject;\r\nend;\r\n\r\nif jsonresobject.get('errorno', JsonResToken) then\r\nerrorno := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('errortext', JsonResToken) then\r\nerrortext := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('status', JsonResToken) then\r\nstatus := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('serverfile', JsonResToken) then\r\nserverfile := jsonrestoken.asvalue.astext;\r\n\r\nend;\r\n\r\nprocedure lesstoFTPget(apikey: Text[100]; ftpuser: Text[20]; ftppassword: Text[20]; ftpserver: Text[20]; ftpdir: Text[100]; ftpfilename: Text[50]; var textfile: text; var errorno: text[2]; var errortext: text[100]; var status: text[100]; var serverfile: text[200]);\r\nvar\r\nTempBlob: Record TempBlob temporary;\r\nJsonResArray: JsonArray;\r\nJsonResToken: JsonToken;\r\nJsonResObject: JsonObject;\r\nhttploadOutStream: OutStream;\r\nhttploadInStream: InStream;\r\nContent: HttpContent;\r\nContentHeaders: HttpHeaders;\r\nClient: HttpClient;\r\nRequest: HttpRequestMessage;\r\nResponse: HttpResponseMessage;\r\nResponseText: text;\r\nPostString: Text;\r\ni: Integer;\r\nBase64: text;\r\n\r\nbegin\r\n\r\nContent.GetHeaders(ContentHeaders);\r\nContentHeaders.Clear();\r\nContentHeaders.Add('Content-Type', 'application\/x-www-form-urlencoded; charset=UTF-8');\r\nTempBlob.Blob.CreateOutStream(httploadOutStream, TextEncoding::UTF8);\r\n\r\npoststring := '&amp;action=get' +\r\n'&amp;apikey=' + apikey +\r\n'&amp;user=' + ftpuser +\r\n'&amp;pass=' + ftppassword +\r\n'&amp;ftpserver=' + ftpserver +\r\n'&amp;ftpdir=' + ftpdir +\r\n'&amp;ftpfilename=' + ftpfilename;\r\n\r\nhttploadOutStream.WriteText(poststring);\r\n\r\nTempBlob.Blob.CreateInStream(httploadInStream, TextEncoding::UTF8);\r\nContent.WriteFrom(httploadInStream);\r\nRequest.Content := Content;\r\nRequest.SetRequestUri('https:\/\/lessto.dk\/cloudtofile\/lessto-ftp-connect');\r\nRequest.Method := 'POST';\r\n\r\nClient.Send(Request, Response);\r\n\r\nResponse.Content().ReadAs(ResponseText);\r\n\r\nResponseText := '[' + ResponseText + ']';\r\nif not JsonResArray.ReadFrom((ResponseText)) then begin\r\nerrorno := '99';\r\nerrortext := 'Connection error';\r\nexit;\r\nend;\r\n\r\nFor i := 0 to jsonresarray.count - 1 do begin\r\njsonResarray.get(i, jsonrestoken);\r\nJsonResObject := jsonrestoken.asobject;\r\nend;\r\n\r\nif jsonresobject.get('errorno', JsonResToken) then\r\nerrorno := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('errortext', JsonResToken) then\r\nerrortext := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('status', JsonResToken) then\r\nstatus := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('base64', JsonResToken) then begin\r\nbase64 := jsonrestoken.asvalue.astext;\r\ntextfile := FromBase64StringToText(base64);\r\nend;\r\n\r\nif jsonresobject.get('serverfile', JsonResToken) then\r\nserverfile := jsonrestoken.asvalue.astext;\r\n\r\nend;\r\n\r\nprocedure lesstoFTPdelete(apikey: Text[100]; ftpuser: Text[20]; ftppassword: Text[20]; ftpserver: Text[20]; ftpdir: Text[100]; ftpfilename: Text[50]; var errorno: text[2]; var errortext: text[100]; var status: text[100]; var serverfile: text[200]);\r\nvar\r\nTempBlob: Record TempBlob temporary;\r\nJsonResArray: JsonArray;\r\nJsonResToken: JsonToken;\r\nJsonResObject: JsonObject;\r\nhttploadOutStream: OutStream;\r\nhttploadInStream: InStream;\r\nContent: HttpContent;\r\nContentHeaders: HttpHeaders;\r\nClient: HttpClient;\r\nRequest: HttpRequestMessage;\r\nResponse: HttpResponseMessage;\r\nResponseText: text;\r\nPostString: Text;\r\ni: integer;\r\n\r\nbegin\r\n\r\nContent.GetHeaders(ContentHeaders);\r\nContentHeaders.Clear();\r\nContentHeaders.Add('Content-Type', 'application\/x-www-form-urlencoded; charset=UTF-8');\r\nTempBlob.Blob.CreateOutStream(httploadOutStream, TextEncoding::UTF8);\r\n\r\npoststring := '&amp;action=delete' +\r\n'&amp;apikey=' + apikey +\r\n'&amp;user=' + ftpuser +\r\n'&amp;pass=' + ftppassword +\r\n'&amp;ftpserver=' + ftpserver +\r\n'&amp;ftpdir=' + ftpdir +\r\n'&amp;ftpfilename=' + ftpfilename;\r\n\r\nhttploadOutStream.WriteText(poststring);\r\n\r\nTempBlob.Blob.CreateInStream(httploadInStream, TextEncoding::UTF8);\r\nContent.WriteFrom(httploadInStream);\r\nRequest.Content := Content;\r\nRequest.SetRequestUri('https:\/\/lessto.dk\/cloudtofile\/lessto-ftp-connect');\r\nRequest.Method := 'POST';\r\n\r\nClient.Send(Request, Response);\r\n\r\nResponse.Content().ReadAs(ResponseText);\r\n\r\nResponseText := '[' + ResponseText + ']';\r\nif not JsonResArray.ReadFrom((ResponseText)) then begin\r\nerrorno := '99';\r\nerrortext := 'Connection error';\r\nexit;\r\nend;\r\n\r\nFor i := 0 to jsonresarray.count - 1 do begin\r\njsonResarray.get(i, jsonrestoken);\r\nJsonResObject := jsonrestoken.asobject;\r\nend;\r\n\r\nif jsonresobject.get('errorno', JsonResToken) then\r\nerrorno := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('errortext', JsonResToken) then\r\nerrortext := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('status', JsonResToken) then\r\nstatus := jsonrestoken.asvalue.astext;\r\n\r\nif jsonresobject.get('serverfile', JsonResToken) then\r\nserverfile := jsonrestoken.asvalue.astext;\r\n\r\nend;\r\n\r\nprocedure TextToBase64String(Value: Text) ReturnValue: Text;\r\nvar\r\nBinaryValue: text;\r\nLength: Integer;\r\nbegin\r\n\/\/ Divide value into blocks of 3 bytes\r\nLength := StrLen(Value);\r\nBinaryValue := TextToBinary(Value, 8);\r\nReturnValue := ConvertBinaryValueToBase64String(BinaryValue, Length);\r\nend;\r\n\r\nprocedure StreamToBase64String(Value: InStream) ReturnValue: Text;\r\nvar\r\nSingleByte: Byte;\r\nLength: Integer;\r\nBinaryValue: Text;\r\nbegin\r\nwhile not Value.EOS do begin\r\nValue.Read(SingleByte, 1);\r\nLength += 1;\r\nBinaryValue += ByteToBinary(SingleByte, 8);\r\nend;\r\n\r\nReturnValue := ConvertBinaryValueToBase64String(BinaryValue, Length);\r\nend;\r\n\r\nprocedure FromBase64StringToText(Value: Text) ReturnValue: Text;\r\nvar\r\nBinaryValue: Text;\r\nbegin\r\nBinaryValue := ConvertBase64StringToBinaryValue(Value);\r\nReturnValue := BinaryToText(BinaryValue);\r\nend;\r\n\r\nprocedure FromBase64StringToStream(Value: Text; var ReturnValue: OutStream);\r\nvar\r\nBinaryValue: Text;\r\nbegin\r\nBinaryValue := ConvertBase64StringToBinaryValue(Value);\r\nBinaryToStream(BinaryValue, ReturnValue);\r\nend;\r\n\r\nlocal procedure ConvertBinaryValueToBase64String(Value: Text; Length: Integer) ReturnValue: Text;\r\nvar\r\nLength2: Integer;\r\nPaddingCount: Integer;\r\nBlockCount: Integer;\r\nPos: Integer;\r\nCurrentByte: text;\r\ni: Integer;\r\nbegin\r\nif Length MOD 3 = 0 then begin\r\nPaddingCount := 0;\r\nBlockCount := Length \/ 3;\r\nend else begin\r\nPaddingCount := 3 - (Length MOD 3);\r\nBlockCount := (Length + PaddingCount) \/ 3;\r\nend;\r\n\r\nLength2 := Length + PaddingCount;\r\nValue := PadStr(Value, Length2 * 8, '0');\r\n\r\n\/\/ Loop through bytes in groups of 6 bits\r\nPos := 1;\r\nwhile Pos &lt; Length2 * 8 do begin\r\nCurrentByte := CopyStr(Value, Pos, 6);\r\nReturnValue += GetBase64Char(BinaryToInt(CurrentByte));\r\npos += 6;\r\nend;\r\n\r\n\/\/ Replace last characters with '='\r\nfor i := 1 to PaddingCount do begin\r\nPos := StrLen(ReturnValue) - i + 1;\r\nReturnValue[Pos] := '=';\r\nend;\r\n\r\nend;\r\n\r\nlocal procedure ConvertBase64StringToBinaryValue(Value: Text) ReturnValue: Text;\r\nvar\r\nBinaryValue: Text;\r\ni: Integer;\r\nIntValue: Integer;\r\nPaddingCount: Integer;\r\nbegin\r\nfor i := 1 to StrLen(Value) do begin\r\nif Value[i] = '=' then\r\nPaddingCount += 1;\r\n\r\nIntValue := GetBase64Number(Value[i]);\r\nBinaryValue += IncreaseStringLength(IntToBinary(IntValue), 6);\r\nend;\r\n\r\nfor i := 1 to PaddingCount do\r\nBinaryValue := CopyStr(BinaryValue, 1, StrLen(BinaryValue) - 8);\r\n\r\nReturnValue := BinaryValue;\r\nend;\r\n\r\nlocal procedure TextToBinary(Value: text; ByteLength: Integer) ReturnValue: text;\r\nvar\r\nIntValue: Integer;\r\ni: Integer;\r\nBinaryValue: text;\r\nbegin\r\nfor i := 1 to StrLen(value) do begin\r\nIntValue := value[i];\r\nBinaryValue := IntToBinary(IntValue);\r\nBinaryValue := IncreaseStringLength(BinaryValue, ByteLength);\r\nReturnValue += BinaryValue;\r\nend;\r\nend;\r\n\r\nlocal procedure BinaryToText(Value: Text) ReturnValue: Text;\r\nvar\r\nBuffer: BigText;\r\nPos: Integer;\r\nSingleByte: Text;\r\nCharValue: Text;\r\nbegin\r\nBuffer.AddText(Value);\r\n\r\nPos := 1;\r\nwhile Pos &lt; Buffer.Length do begin\r\nBuffer.GetSubText(SingleByte, Pos, 8);\r\nCharValue[1] := BinaryToInt(SingleByte);\r\nReturnValue += CharValue;\r\nPos += 8;\r\nend;\r\nend;\r\n\r\nlocal procedure BinaryToStream(Value: Text; var ReturnValue: OutStream);\r\nvar\r\nBuffer: BigText;\r\nPos: Integer;\r\nSingleByte: Text;\r\nByteValue: Byte;\r\nbegin\r\nBuffer.AddText(Value);\r\n\r\nPos := 1;\r\nwhile Pos &lt; Buffer.Length do begin\r\nBuffer.GetSubText(SingleByte, Pos, 8);\r\nByteValue := BinaryToInt(SingleByte);\r\nReturnValue.Write(ByteValue, 1);\r\nPos += 8;\r\nend;\r\nend;\r\n\r\nlocal procedure ByteToBinary(Value: Byte; ByteLenght: Integer) ReturnValue: Text;\r\nvar\r\nBinaryValue: Text;\r\nbegin\r\nBinaryValue := IntToBinary(Value);\r\nBinaryValue := IncreaseStringLength(BinaryValue, ByteLenght);\r\nReturnValue := BinaryValue;\r\nend;\r\n\r\nlocal procedure IntToBinary(Value: integer) ReturnValue: text;\r\nbegin\r\nwhile Value &gt;= 1 do begin\r\nReturnValue := Format(Value MOD 2) + ReturnValue;\r\nValue := Value DIV 2;\r\nend;\r\nend;\r\n\r\nlocal procedure BinaryToInt(Value: Text) ReturnValue: Integer;\r\nvar\r\nMultiplier: BigInteger;\r\nIntValue: Integer;\r\ni: Integer;\r\nbegin\r\nMultiplier := 1;\r\nfor i := StrLen(Value) downto 1 do begin\r\nEvaluate(IntValue, CopyStr(Value, i, 1));\r\nReturnValue += IntValue * Multiplier;\r\nMultiplier *= 2;\r\nend;\r\nend;\r\n\r\nlocal procedure IncreaseStringLength(Value: Text; ToLength: Integer) ReturnValue: Text;\r\nvar\r\nExtraLength: Integer;\r\nExtraText: Text;\r\nbegin\r\nExtraLength := ToLength - StrLen(Value);\r\n\r\nif ExtraLength &lt; 0 then\r\nexit;\r\n\r\nExtraText := PadStr(ExtraText, ExtraLength, '0');\r\nReturnValue := ExtraText + Value;\r\nend;\r\n\r\nlocal procedure GetBase64Char(Value: Integer): text;\r\nvar\r\nchars: text;\r\ni: Integer;\r\nbegin\r\nchars := Base64Chars;\r\nexit(chars[Value + 1]);\r\nend;\r\n\r\nlocal procedure GetBase64Number(Value: text): Integer;\r\nvar\r\nchars: text;\r\nbegin\r\nif Value = '=' then\r\nexit(0);\r\n\r\nchars := Base64Chars;\r\nexit(StrPos(chars, Value) - 1);\r\nend;\r\n\r\nlocal procedure Base64Chars(): text;\r\nbegin\r\nexit('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\/');\r\nend;\r\n\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>lessto CloudToFile Demo of Business Central 365 spring edition (14) where data is transferred to and from a FTP site. A simple cloud to file function. Code for Business Central 365 Wave 2 (15) Simpel demo of the four FTP commands The full wordpress code from the demo. The code works both in local installation, &#8230; <a title=\"lessto &#8211; BC365 spring &#8211; code &#8211; example &#8211; eng\" class=\"read-more\" href=\"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-spring-code-example-eng\/\" aria-label=\"More on lessto &#8211; BC365 spring &#8211; code &#8211; example &#8211; eng\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>lessto - BC365 spring - code - example - eng - CloudToFile<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-spring-code-example-eng\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"lessto - BC365 spring - code - example - eng - CloudToFile\" \/>\n<meta property=\"og:description\" content=\"lessto CloudToFile Demo of Business Central 365 spring edition (14) where data is transferred to and from a FTP site. A simple cloud to file function. Code for Business Central 365 Wave 2 (15) Simpel demo of the four FTP commands The full wordpress code from the demo. The code works both in local installation, ... Read more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-spring-code-example-eng\/\" \/>\n<meta property=\"og:site_name\" content=\"CloudToFile\" \/>\n<meta property=\"article:modified_time\" content=\"2019-12-13T20:00:19+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" value=\"Written by\">\n\t<meta name=\"twitter:data1\" value=\"lssto\">\n\t<meta name=\"twitter:label2\" value=\"Est. reading time\">\n\t<meta name=\"twitter:data2\" value=\"9 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/lessto.dk\/cloudtofile\/#website\",\"url\":\"https:\/\/lessto.dk\/cloudtofile\/\",\"name\":\"CloudToFile\",\"description\":\"Cloud FTP and Print service\",\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-spring-code-example-eng\/#webpage\",\"url\":\"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-spring-code-example-eng\/\",\"name\":\"lessto - BC365 spring - code - example - eng - CloudToFile\",\"isPartOf\":{\"@id\":\"https:\/\/lessto.dk\/cloudtofile\/#website\"},\"datePublished\":\"2019-11-28T10:59:22+00:00\",\"dateModified\":\"2019-12-13T20:00:19+00:00\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/lessto.dk\/cloudtofile\/lessto-bc365-spring-code-example-eng\/\"]}]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/pages\/183"}],"collection":[{"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/comments?post=183"}],"version-history":[{"count":10,"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/pages\/183\/revisions"}],"predecessor-version":[{"id":213,"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/pages\/183\/revisions\/213"}],"wp:attachment":[{"href":"https:\/\/lessto.dk\/cloudtofile\/wp-json\/wp\/v2\/media?parent=183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}