Working with Binary Data using SXML
Binaries in Smartsite iXperion are wrapped in DataTables, because Byte Arrays have not SXML equivalen.
In most scenarios however, SXML abstracts usage of binary data.
For example, when uploading and storing files on the server filesystem, you don't see anything of the byte array handling:
Smartsite SXML | Copy Code |
---|---|
<form class="CoolForm" action="{request.location()}" method="post" enctype="multipart/form-data"> <fieldset> <legend>Your images</legend> <input class="Required MultiFile TextBox" id="files" type="file" name="files"/> <br /> <input type="submit" value="Save"/> </fieldset> </form> <se:if expression="request.method()=='POST'" error="Error saving files: {this.error.message()}"> Uploaded: <se:format inputdata="{request.files()}" > <se:rowformat> {request.savefile(this.field(key), '/temp/'+this.field(filename))} Saved {this.field(filename)} <br /> </se:rowformat> </se:format> </se:if> |
Personalization/Global Storage
In personalization (and in Global Storage), file data is stored in profile properties, but again, no byte array handling is needed, since the code needed to do so abstracts it for you:
ShowForm() (see the My Profile Smartlet in personalization)
Smartsite SXML | Copy Code |
---|---|
<se:format inputdata="{request.files()}" > <se:rowformat match="first"> {personalization.set('', Avatar, request.getfiledata(this.field(key)))} </se:rowformat> </se:format> |
The only place in which the actual byte array is used, is in the Image() translation within the My Profile Smartlet, because it needs to be sent accross the wire in the response.
Here, you can use the datatable.getbytes() viper method to give you the actual byte array stored inside the wrapping datatable:
XML | Copy Code |
---|---|
{buffer.set(img, personalization.get('', 'Avatar'))} {response.setlastmodified(datatable.getvalue($img, 'UploadDateTime'))} {page.setforcedresult(datatable.getbytes($img), 'image/jpeg')} |
Physical files on the server
With physical files on disk, it's practically the same story again: no byte array handling, but DataTable wrapping:
Smartsite SXML | Copy Code |
---|---|
{buffer.set(file, filesystem.readbinarydata('/assets/images/ng/Clouds.jpg'))} |
You can see that by simply outputting the buffer:
Smartsite SXML | Copy Code |
---|---|
{buffer.get(file)} |
You should see something like this:
Smartsite SXML | Copy Code |
---|---|
SXMLDataTable (Name=FileContents; Rows=1; Columns=FileName,ContentLength,Bytes) |
Item Data and Database query results
Now, when binary data is retrieved from the database (for instance using sqlquery), or indirectly using SXML (itemdata.field() vipers, itemdata macro), you get actual byte arrays:
Smartsite SXML | Copy Code |
---|---|
{itemdata.field(binarydata, IMG_CLOUDS)} |
This will output:
Smartsite SXML | Copy Code |
---|---|
(object: System.Byte[]) |
You can use the convert.tobinarytable() viper to do the wrapping:
Smartsite SXML | Copy Code |
---|---|
{buffer.set(file, convert.tobinarydatatable(itemdata.field(binarydata, IMG_CLOUDS)))} {filesystem.writebinarydata("/temp/clouds.jpg", $file)} |
Now, you can use any of the methods mentioned above to work with the binary data.
Storing data in the database
When storing binary data in the database, you have to get the byte array from a wrapping datatable:
Smartsite SXML | Copy Code |
---|---|
{buffer.set(bin, datatable.getbytes($img))} |
Now, using sqlquery.executenonquery(), you can store the binary data:
Smartsite SXML | Copy Code |
---|---|
{sql.executenonquery("insert into BinTable (BinData) VALUES(?)", $bin)} |
... or you can use the sqlquery macro (Note: 1.4+ needed for binary sql params):
Smartsite SXML | Copy Code |
---|---|
<se:sqlquery mode="nonquery"> <se:parameters> <se:parameter name="sql"> UPDATE Contents SET CtSpecificBinary1=? WHERE Nr=? </se:parameter> <se:parameter name="params"> <se:collection> <se:member type="binary">{buffer.get(bin)}</se:member> <se:member type="integer">{itemdata.number()}</se:member> </se:collection> </se:parameter> </se:parameters> </se:sqlquery> |
Binary data stored in Xml (base64 encoded)
In this example, you can see how to retrieve binary data from Xml using the this.extractbinary() local viper method of the xmlprocessor macro.