Written by

Prinicipal Technical Specialist - Trakcare Client Development at Intersystems
Question Chris Stewart · Oct 7, 2016

Setting properties on GlobalBinary stream

Hi


I have been working on changing a web application from using %FileBinaryStream to storing and serving the file content from a %Stream.GlobalBinary property, stored in a new database.  I have managed to migrate the data across, and have also been able to redirect the stream so that it is being served through the web link.  However, the previous method set attributes on the File stream to have the stream be rendered as the original file type through MIME, using this code

do stream.SetAttribute("ContentDisposition","inline; filename="_filecvt)

This method is not supported by %Stream.GlobalBinary, and I can't see a way in the documentation to add this sort of attribute to the stream.  How can I have the stream render as the original "file"?

Thanks

CHris

Comments

Tomas Vaverka · Oct 7, 2016

The %Stream.GlobalBinary/GlobalCharacter doesn't support to add/save Attributes. You would need to use the %Library stream classes to be able to do it - %Library.GlobalBinaryStream/%Library.GlobalCharacterStream.

The reason is in difference how the ID of the stream is created and saved in persistent data. For %Stream.GlobalBinary/GlobalCharacter only the ID number is stored in database, while for %Library.GlobalBinaryStream/%Library.GlobalCharacterStream the full OID is saved to database and it contains also name of the global (=stream location) and type of the stream. The ID of such stream contains also all added attributes.

Here is an example:

Class Test.streamtest Extends %Persistent{Property Stream1 As %Stream.GlobalCharacter;Property Stream2 As %GlobalCharacterStream;ClassMethod FillData() As %Status{
  // kill existing dataDO ##class(Test.streamtest).%KillExtent()KILL ^Test.streamtestS  // create a new recordSET obj=##class(Test.streamtest).%New()DO obj.Stream1.Write("Stream1 data")DO obj.Stream2.Write("Stream2 data")DO obj.Stream2.SetAttribute("ContentDisposition","inline; filename=test.txt")SET sc=obj.%Save()  // display id of streamsSET id1=obj.Stream1.%Id() ZWRITE id1SET id2=obj.Stream2.%Id() ZWRITE id2  // display stored dataWRITE ! ZWRITE ^Test.streamtestD,^Test.streamtestSQUIT sc}}

And result:

USER>d ##class(Test.streamtest).FillData()
id1=1
id2=$c(0,24,1,19,1)_"^Test.streamtestS"_$c(3,4,2)_"3"_$c(1)_"1"_$c(1,20,1)_
"ContentDisposition"_$c(27,1)_"inline; filename=test.txt"
 
^Test.streamtestD=1
^Test.streamtestD(1)=$lb("","1",$lb($c(0,24,1,19,1)_
"^Test.streamtestS"_$c(3,4,2)_"3"_$c(1)_"1"_$c(1,20,1)_
"ContentDisposition"_$c(27,1)_"inline; filename=test.txt","%Library.GlobalCharacterStream"))
^Test.streamtestS=2
^Test.streamtestS(1)=1
^Test.streamtestS(1,0)=12
^Test.streamtestS(1,1)="Stream1 data"
^Test.streamtestS(2)=1
^Test.streamtestS(2,0)=12
^Test.streamtestS(2,1)="Stream2 data"
0
Chris Stewart  Oct 7, 2016 to Tomas Vaverka

Thanks Tomas, I will rewrite my class to use the %GlobalCharacterStream

0