How do I make an ANSI file on a FTP server?
This is in Axapta 2009.
I have the code below, that can make an utf-8 file on a FTP server with username and password. That works fine.
The only problem is that I need to save the file as ANSI, so the Danish letters are correct.
In the Axapta 2009 program, I make an ANSI file in the Windows temp folder. That file is correct, but when I use the code below to send it to the FTP server, the Danish letters get wrong.
I hope you can help!
Best regards,
Morten
public void uploadFiletoFTPServer(str _fileNameTmp, str _fileNameFtp)
{
System.Object request,response,credential;
System.IO.StreamReader streamReader;
System.IO.Stream requestStream;
System.Array files;
System.Net.FtpWebRequest ftpRequest;
System.Net.FtpWebResponse ftpResponse;
System.Byte[] bytes;
System.Text.Encoding myEncoding;
System.Exception sysException;
Str 120 TempPath,executedate;
str timeinstr,nextFile;
Commaio file;
container line;
Filename filepath,fileType, ftpFileName;
System.Net.ICredentials iCredentials;
System.Net.IWebProxy iWebProxy;
;
try
{
ftpFileName = "ftp...//myFile";
streamReader = new System.IO.StreamReader(_fileNameTmp);
// must be ANSI:
myEncoding = System.Text.Encoding::get_UTF8();
//myEncoding = System.Text.Encoding::get_Default();
//myEncoding = System.Text.Encoding::get_Unicode();
//myEncoding = System.Text.Encoding::GetEncoding(1252);
//myEncoding = System.Text.Encoding::get_ASCII();
//myEncoding = System.Text.Encoding::get_BigEndianUnicode();
//myEncoding = System.Text.Encoding::GetEncoding(865);
//myEncoding = System.Text.Encoding::GetEncoding(65001);
bytes = myEncoding.GetBytes(streamReader.ReadToEnd());
streamReader.Close();
request = System.Net.WebRequest::Create(new System.Uri(ftpFileName));
ftpRequest = request;
credential = new System.Net.NetworkCredential("myUserId", "myPassword");
iCredentials = credential;
ftpRequest.set_Credentials(iCredentials);
ftpRequest.set_ContentLength(bytes.get_Length());
ftpRequest.set_Method("STOR");
requestStream = ftpRequest.GetRequestStream();
requestStream.Write(bytes,0,bytes.get_Length());
requestStream.Close();
response = ftpRequest.GetResponse();
ftpResponse = response;
}
catch(Exception::CLRError)
{
sysException = CLRInterop::getLastException();
info(sysException.get_Message());
}
CodeAccessPermission::revertAssert();
}
Answers
-
Hi Morten,
I'm Danish too, but let's keep it in Danish for any potential foreign visitors :)
Everyting from this paragraph down is output from a program a friend of mine just developed called - I have his permission to post this here:
***
The root cause is that AX 2009 internally works with Unicode (UTF-16), but your FTP target system expects ANSI encoding (codepage 1252 / Windows-1252) where Danish characters like æøå are single bytes. The fix is to use
TextIowith an explicit codepage parameter when writing the file, then upload via FTP using a COM object.Here is a complete working solution:
Approach
Use
TextIowith codepage 1252 (Western European ANSI) to write a properly encoded temp file, then upload it via FTP using a COM-based helper class. The key insight most examples miss is the third parameter on theTextIoconstructor — that is where encoding is controlled.Verified X++ Code
// Helper class for ANSI FTP uploads class CustAnsiFileUploader { str ftpServer; str ftpUsername; str ftpPassword; str tempPath; } void new() { ; tempPath = WinAPI::getTempPath(); } public str parmFtpServer(str _ftpServer = ftpServer) { ; ftpServer = _ftpServer; return ftpServer; } public str parmFtpUsername(str _ftpUsername = ftpUsername) { ; ftpUsername = _ftpUsername; return ftpUsername; } public str parmFtpPassword(str _ftpPassword = ftpPassword) { ; ftpPassword = _ftpPassword; return ftpPassword; } public boolean uploadTextAsAnsi(str textContent, str remoteFileName) { str tempFileName; boolean uploadSuccess; TextIo textIo; container textLines; int i; str currentLine; ; tempFileName = tempPath + strReplace(newGuid(), '-', '') + ".txt"; uploadSuccess = false; try { // Codepage 1252 = Western European ANSI — handles æøåÆØÅ correctly textIo = new TextIo(tempFileName, #io_write, 1252); if (!textIo) { throw error("Could not create temporary ANSI file"); } textLines = str2con(textContent, '\n'); for (i = 1; i <= conLen(textLines); i++) { currentLine = conPeek(textLines, i); textIo.write(currentLine); } textIo = null; // Setting to null closes and flushes the file if (!WinAPI::fileExists(tempFileName)) { throw error("Failed to create ANSI file"); } uploadSuccess = this.uploadFileViaFtp(tempFileName, remoteFileName); if (uploadSuccess) { info(strFmt("File uploaded successfully as ANSI: %1", remoteFileName)); } else { error("Failed to upload ANSI file to FTP server"); } } catch (Exception::Error) { uploadSuccess = false; error("Failed to process ANSI file upload"); } // Clean up temporary file if (WinAPI::fileExists(tempFileName)) { WinAPI::deleteFile(tempFileName); } return uploadSuccess; } private boolean uploadFileViaFtp(str localFilePath, str remoteFileName) { COM ftpObject; COM ftpFolder; boolean uploadSuccess; str ftpUrl; ; uploadSuccess = false; try { // Build FTP URL with credentials ftpUrl = strFmt("ftp://%1:%2@%3", ftpUsername, ftpPassword, ftpServer); ftpObject = new COM("Shell.Application"); if (!ftpObject) { throw error("Failed to create FTP COM object"); } ftpFolder = ftpObject.NameSpace(ftpUrl); if (!ftpFolder) { throw error("Failed to connect to FTP server"); } // CopyHere flag 16 = suppress all dialogs automatically ftpFolder.CopyHere(localFilePath, 16); sleep(2000); // Wait for upload to complete uploadSuccess = true; info(strFmt("File uploaded to FTP: %1", remoteFileName)); } catch (Exception::Error) { uploadSuccess = false; error("FTP upload failed"); } catch (Exception::CLRError) { uploadSuccess = false; error("FTP COM error occurred"); } ftpFolder = null; ftpObject = null; return uploadSuccess; } // Usage example static void example() { CustAnsiFileUploader uploader; str textWithDanishChars; ; uploader = new CustAnsiFileUploader(); uploader.parmFtpServer("ftp.yourserver.com"); uploader.parmFtpUsername("ftpuser"); uploader.parmFtpPassword("ftppass"); textWithDanishChars = "Rød grød med fløde\n"; textWithDanishChars += "Blåbærgrød"; if (uploader.uploadTextAsAnsi(textWithDanishChars, "danish_test.txt")) { info("Upload completed successfully"); } else { error("Upload failed"); } }Detailed Explanation
Section
Purpose
Class declaration
Instance variables for FTP credentials and temp path
new()Constructor initialises temp path using
WinAPI::getTempPath()parmFtp*methodsStandard AX 2009 parm pattern for setting credentials
uploadTextAsAnsi()Main method — creates the ANSI file via TextIo, then calls upload
new TextIo(tempFileName, #io_write, 1252)The critical line — codepage 1252 controls Western European ANSI encoding
textIo = nullSetting to null closes and flushes buffers (no explicit
.close()needed in AX 2009)uploadFileViaFtp()COM-based FTP upload using Shell.Application
CopyHere(localFilePath, 16)Uploads the file; flag 16 suppresses Windows dialogs
Temp file cleanup
WinAPI::deleteFile()— always clean up; AX 2009 will not do it for youWhy this matters: The receiving system expects ANSI encoding where Danish characters æøå are single bytes (0xE6, 0xF8, 0xE5). If you write the file without specifying codepage, AX 2009 uses the system default which may be UTF-8 or UTF-16, producing garbled output on the other end.
Codebase Fit
This solution uses
TextIowith an explicit codepage parameter, which is the standard AX 2009 pattern for file exports requiring specific encoding. The temp file approach (write locally, upload, delete) is reliable and avoids holding connections open during encoding conversion. TheShell.ApplicationCOM object is a well-established AX 2009 technique for FTP operations. For batch jobs that run frequently or with large files, the WinInet DLL approach gives more direct control over the FTP connection — but for most use casesShell.Applicationis sufficient.Learning Point — Text Encoding in AX 2009 File Operations
Understanding text encoding is essential for enterprise integrations. AX 2009 internally uses Unicode (UTF-16), but external systems often require specific encodings. The
TextIoclass is AX 2009's primary tool for encoding control via the codepage parameter:- 1252 — Western European ANSI (Danish, Norwegian, German special characters)
- 1250 — Central European ANSI
- 65001 — UTF-8
- 0 or omitted — System default ANSI codepage
Binary vs Text FTP transfer: FTP has two transfer modes. Text mode performs line-ending conversions which can corrupt carefully encoded files. Binary mode transfers exact bytes, preserving the encoding written by
TextIo. Always use binary mode when encoding matters.Debugging tip: If characters still appear wrong after implementing this:
- Open the generated file in a hex editor and verify the bytes (æ should be 0xE6 in Windows-1252, not 0xC3 0xA6 as in UTF-8)
- Confirm the receiving system's expected codepage (might be 850 for old DOS systems, or ISO-8859-1 for Unix)
- Test with a known-good ANSI file created in Notepad saved explicitly as "ANSI"
Resource management: AX 2009 lacks automatic disposal, so always clean up explicitly. Set COM objects to null, and delete temporary files. This prevents resource leaks in long-running batch jobs.
***
I hope this helped! Again, all credit goes to
:)
— Hans
0
Categories
- All Categories
- 75 General
- 75 Announcements
- 66.7K Microsoft Dynamics NAV
- 18.8K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 610 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 253 Dynamics CRM
- 103 Dynamics GP
- 6 Dynamics SL
- 1.5K Other
- 991 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 28 Design Patterns (General & Best Practices)
- Architectural Patterns
- 9 Design Patterns
- 4 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1K General Chat
- 1.6K Website
- 77 Testing
- 1.2K Download section
- 23 How Tos section
- 249 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions