go to post Kevin B Lavallee · Jan 19, 2024 Hello. This is a followup after my work with this. We implemented the code but ran into an issue with unprintable characters. We use wingding fonts for some of our data in tables. We could not figure out why messages with unprintable characters got lost in transmission and never got from the server to the client. It turns out that the issue is the fact that the "head" (header) variable was being created based on the size of the stream "before UTF8 conversion". So if the original data size was 500 characters, the header was indicating that the message size was 500. Then, as the data is read in chunks from the stream and the UTF8 conversion was done, there was one unprintable (char 252) that was in the data, causing the converted data size to be 501 characters which cause the message transmission to fail. To address this, we had to delay the creation of the header until all of the data was read from the stream, UTF8 converted and save into a process private global. Once the entire stream was UTF8 translated into the PPG, we derived the new length of the data and then looped through the PPG and wrote everything to the websocket and that fixed the problem. I am not thrilled with having to have the data go through two intermediate steps to get it from the dynamic object to the websocket, but, because the UTF8 conversion of unprintable characters, I saw no alternative. Is there any chance there is another option that anyone is aware of that would allow me to determine the UTF8 character count of the stream without going through a process private global? Thanks again for the continued support. Here is a portion of the code from my writeStream method that deals with the new order of processing: ... do data.Rewind()// Convert ASCII stream into UTF8 temp globalset streamSeq = 0set dataLength = 0while ('data.AtEnd) { set bufferBlock = data.Read(.BUFSZ) // Convert UTF8 if we aren't using Binary Web Sockets if i%BinaryData '= 1 { try { set bufferBlock=$zconvert(bufferBlock,"O","UTF8") } catch exp { set bufferBlock=bufferBlock } } set ^||streamData($i(streamSeq)) = bufferBlock set dataLength = dataLength + $length(bufferBlock)} // Write header to the socketif ((i%WSClassProtocolVersion > 1) && (i%WSDataFraming = 1)) { set head = $ZLChar(dataLength) if (i%BinaryData = 1) set head = head_"8" else set head = head_"7" } else { set head = ""}write head // Loop through temp global and write to the socketset seq = 0for { set seq = $order(^||streamData(seq)) if (seq = "") { quit } write ^||streamData(seq)} // Send a flush command nowwrite *-3...
go to post Kevin B Lavallee · Oct 11, 2022 Thank you Julius for explaining why this does not work on websockets and for the suggestion about the WriteStream method. I did use Nicholai's sample method to implement the changes to work around this issue. Much appreciated.
go to post Kevin B Lavallee · Oct 11, 2022 Thank you Nicholai for this method. I made a few modifications to the code but I very much appreciate the great starting point.
go to post Kevin B Lavallee · May 26, 2022 Thanks Dmitry. This worked perfectly and fixed an issue we had with a vendor that wanted empty fields removed from messages sent to them. Much appreciated.