Using base64 encoding and decoding for file transfer in AX 2012
Base64 BinData
If you want to transfer small file data using AX and do not want to make use of shared folders or file uploading, sending your file directly inside your XML message as base64 encoded string is a good option. Base64 gives you the possibility to encode your binary data as text and transfer it inside text based message types like XML and JSON and decode it back as a file on the receipt.
For big files though, like 10MB and bigger, I recommend using binary file transfer instead of base64.
Ax 2012 has built in support for decoding and encoding base64 data type with some missing things and drawback we will mention in this article. I do recommend using AX standard methods to do it and not .NET equivalents in AX 2012, because I doubt marshalling such huge amount of data between CLR Interop and AX performs good enough.
Encoding base64 from AX data
For decoding from AX table stored, container based data, simply use the following function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public str base64FromData(container _data) { str base64; Bindata bindata; if (_data!=conNull()) { bindata = new bindata(); bindata.setData(_data); base64 = bindata.base64Encode(); } return base64; } |
You can use the same bindata class to load a file from disk instead of loading a container based binary data from database. Do not forget to add a CLR interop permission for this to avoid the error :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
///..................... path = docuRef.completeFilename(); fileIOPerm = new FileIOPermission(path, 'r' ); permissionSet.add(fileIOPerm); interopPerm = new InteropPermission(InteropKind::ClrInterop); permissionSet.add(interopPerm); CodeAccessPermission::assertMultiple(permissionSet); fileExists = System.IO.File::Exists(path); if (fileExists) { bindata.loadFile(path); base64 = bindata.base64Encode(); } //////////////..................... |
If you want to encode simple text (or memo, string) using base64 and send it as base64, you need to load the string to bindata class using setAsciiData() method. Note that bindata class also has a setText() method, we are NOT using that one, it will encode it wrong if you do so:
1
2
3
|
str Memo = "a string "; bindata.setAsciiData(Memo); |
After your file is decoded you can add it directly as a node value in your XML document.
Decoding base64 file from a document
Here is the tricky part, AX decodes base64 fine but causing some problems on base64 prefixes. It does not recognize them. To be able to decode it, you manually need to remove the headers, like the example below, and decode it :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public container dataFromBase64(str _base64) { int pos; BinData bindata; str base64, base64ext; container data; base64 = _base64; base64ext = '' ; if (base64!= '' ) { pos = strFind(base64, ';' , 1, 60); if (pos) { base64ext = subStr(base64, 1, pos-1); } pos = strFind(base64, ',' , 1, 60); base64 = strDel(base64, 1, pos); bindata = new bindata(); data = BinData::loadFromBase64(base64); bindata.setData(data); } return data; } |
What are those headers and when they come. Some types of base64 data, for example photos taken from a cellphone camera in base64 encoding or images used in web, has descriptor prefix before the data starts. Such as the data below. You can erase them to be able to encode, or store them in a variable, like the code above to determine the file extension of the data later.
After you decode your data into container, you can load it into bindata class (like example above) and save it as file or another form of data using bindata class.
Here are some more tips for you if you want to decode base64 and store it inside AX:
- Do not store big file data in a container or string memo blob field in an AX table if you plan to use that table in AX user interface, like inside a form. Create a separate table to store the data and reference other tables to that one if they want to use the file data. It gives all sorts of problems if you store your data in a table used in a form or other UI object, for example if you want to delete the data from the form, it crashes the client (whereas deleting from the code works fine from the same table).
- If you like to store the XML message you have received with file data, for logging or archive purposes, first strip all the file data out of it and do not store the XML text including base64 data inside. You will again have similar problems like above and if you use AIF XML viewer, it will take ages to load that XML into the viewer. You can replace base64 text with the recid of the data you have stored in your data storage table.
posted on 2023-04-27 09:11 lingdanglfw 阅读(67) 评论(0) 编辑 收藏 举报