How do I pass a byte array from JavaScript to an ActiveX control.
My JavaScript will call WCF server (method) and that method will return a byte array.
After that I need to pass this byte array to the ActiveX control.
Could anybody provide me a solution for this?
Depending on what binding your WCF service uses (and as you are calling it from javascript I assume webHttpBinding) it is quite possible that the returned byte array will be returned as a base 64 encoded string. So you might need to modify the ActiveX component to accept a base 64 encoded string as parameter instead of a byte array.
From javascript you will have a form of base64_encode string. ActiveX component should have a function to convert string to byte array like this
byte[] string2byte(string s)
{
byte[] b = new byte[s.Length / 2];
for (int i = 0; i < s.Length; i += 2) { b[i / 2] = Convert.ToByte(s.Substring(i, 2), 16); }
return b;
}
I solved the problem by returning base64string rather than a byte array from the WCF Service.
So that i can simply convert the Base64 string usning Convert.FromBase64String() method to byte arrary.
Related
I am trying to pass an array of byte from Blazor Client to a javascript function:
private async void ShowImage()
{
SelectedImageBytes = await GetImageData();
if (SelectedImageBytes.Any())
{
ReceivedDataLength = SelectedImageBytes.Length;
//ReceivedDataLength is 131072, which is correct
JS.InvokeVoidAsync("JS.setImage", SelectedImageBytes, 256, 256);
}
StateHasChanged();
}
On Javascript side:
function setImage(data, width, height)
{
console.log("On Javascript I have received an array of " + data.length);
//data.length is 174764
console.log(data);
//...
}
console.log(data) outputs the following:
Which seems to me a base64 string representation of my binary data. According wikipedia the size is incremented approximately by 33% going from byte array to base64 string representation, and this is true for this case: 131072 * 1.33 ~ 174764
My questions then are:
How to pass and receive a byte array from Blazor (C#) to Javascript without converting it to a string
If the previous is not possible, what is the best way to convert the base64 string to byte array on Javascript side.
I gave it another go:
C#
public void CallJsUnMarshalled()
{
var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;
unmarshalledRuntime.InvokeUnmarshalled<byte[], int>("JsFunctions.MyFunctionUnmarshalled", MyBytes);
}
Javascript:
function MyFunctionUnmarshalled(bytes)
{
const dataPtr = Blazor.platform.getArrayEntryPtr(bytes, 0, 4);
const length = Blazor.platform.getArrayLength(bytes);
var shorts = new Int16Array(Module.HEAPU8.buffer, dataPtr, length);
return 0;
}
InvokeUnmarshalled requires a return it appears, therefore int in the template arguments. Instead of this probably a reference to the object has to be returned to dispose it. I would appreciate if someone can comment on this (will javascript free that memory when the byte array is not used anymore?).
First tests show an improvement of a factor of 50!
When you are using the interop service, the documentation says:
InvokeAsync takes an identifier for the JavaScript function that you wish to invoke along with any number of JSON-serializable arguments.
So what you observe is the serialization of your byte array into a base64 string, which is the out-of-the-box behavior. So, you are right. I haven't spotted a way to influence the serialization behavior of the JSInterop service.
The Blazer framework in .NET 5 offers you a way to skip the serialization overhead: IJSUnmarshalledRuntime.
But, in my experiments, it can't handle a byte array or any arrays at all.
To answer your second question, have a look at this discussion.
Convert base64 string to ArrayBuffer
When I encrypt the string g.b#yahoo.it in Javascript using the BTOA function I get the result Zy5iQHlhaG9vLml0.
This function converts the string to the base64 representation of the string. When I try and do the equivalent in SAS I get a different value:
proc fcmp outlib=common.funcs.funcs;
function b64(string $) $;
length digest $32767;
digest=strip(put(string,$base64x32767.));
return(digest);
endsub;
quit;
data email;
input email $12.;
datalines;
g.b#yahoo.it
run;
data X;
set email;
e1 = "<" || trim(email) || ">";
pw_e = b64(e1);
put _all_;
run;
Gives me:
email=g.b#yahoo.it e1=<g.b#yahoo.it> pw_e=PGcuYkB5YWhvby5pdD4= _ERROR_=0 _N_=1
Based on the documentation for each, they are using the same alphabet:
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003161924.htm
https://www.w3schools.com/jsref/met_win_btoa.asp
I want to replicate the same function in SAS Data Step to obtain the same result. Is there a way to do this in SAS?
They are doing the same thing. You are modifying the string that you are passing to the base64 encoding function in SAS which is why you are getting a different result. The string you are using in SAS is <g.b#yahoo.it> (you added the < and > characters around it.
If you run that same string of <g.b#yahoo.it> through btoa() you get the same result of PGcuYkB5YWhvby5pdD4=
I have large Javascript objects which I would like to encode to base-64 for AWS Kinesis`
It turns out that:
let objStr = new Buffer(JSON.stringify(obj), 'ascii');
new Buffer(objStr, 'base64').toString('ascii') !== objStr
I'm trying to keep this as simple as possible.
How can I base-64 encode JSON and safely decode it back to its original value?
From String to Base-64
var obj = {a: 'a', b: 'b'};
var encoded = btoa(JSON.stringify(obj))
To decode back to actual
var actual = JSON.parse(atob(encoded))
For reference look here.
https://developer.mozilla.org/en/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
You misunderstood the Buffer(str, [encoding]) constructor, the encoding tells the constructor what encoding was used to create str, or what encoding the constructor should use to decode str into a byte array.
Basically the Buffer class represents byte streams, it's only when you convert it from/to strings that encoding comes into context.
You should instead use buffer.toString("base64") to get base-64 encoded of the buffer content.
let objJsonStr = JSON.stringify(obj);
let objJsonB64 = Buffer.from(objJsonStr).toString("base64");
When converting object to base64 I was getting out of latin range issues and character invalid error.
I made it work in my project with the below line.
Include the base64 and utf8 node packages and access them like this:
var bytes = base64.encode(utf8.encode(JSON.stringify(getOverviewComments())));
You can easily encode and decode from and to JSON/Base64 using a Buffer:
JSON to Base64:
function jsonToBase64(jsonObj) {
const jsonString = JSON.stringify(jsonObj)
return Buffer.from(jsonString).toString('base64')
}
Base64 to JSON:
function encodeBase64ToJson(base64String: string) {
const jsonString = Buffer.from(base64String,'base64').toString()
return JSON.parse(jsonString)
}
atob() and btoa() are outdated and should no longer be used.
How do I convert an array of bytes into ArrayBuffer in Nashorn? I am trying to insert binary data into a pure JavaScript environment (i.e., it doesn't have access to Java.from or Java.to) and so would like to create an instance out an array of bytes.
Looks like I was going about this the wrong way. It made more sense to convert it into Uint8Array since what I'm sending in is an array of bytes.
I created the following function:
function byteToUint8Array(byteArray) {
var uint8Array = new Uint8Array(byteArray.length);
for(var i = 0; i < uint8Array.length; i++) {
uint8Array[i] = byteArray[i];
}
return uint8Array;
}
This will convert an array of bytes (so byteArray is actually of type byte[]) into a Uint8Array.
I think you're right about using a Uint8Array, but this code might be preferable:
function byteToUint8Array(byteArray) {
var uint8Array = new Uint8Array(byteArray.length);
uint8Array.set(Java.from(byteArray));
return uint8Array;
}
Also, if you really need an ArrayBuffer you can use uint8Array.buffer.
My javascript code sends blobs of data to a handler in C#. My Javascript code is working fine, and I have already tried to receive the data from client(javascript) and pass them to the C# handler and save them in a local Folder.
Instead of saving the data in a folder, I want to now save it in a string.
My handler each time gets a piece of my information as a byte[].
my Javascript:
xhr = new XMLHttpRequest();
// this is not the complete code
// I slice my file and push them in var blobs = [];
blobs.push(file.slice(start, end));
while (blob = blobs.shift()) {
xhr.send(blob);
count++;
}
My C# handler: In here, the bool ok never gets set to true.
How can I get all my files chunk by chunk as I am sending them from javascript; and, instead of saving in a folder, saving it in a string?
public void ProcessRequest(HttpContext context)
{
try
{
byte[] buffer = new byte[context.Request.ContentLength];
context.Request.InputStream.Read(buffer, 0, context.Request.ContentLength);
string fileSize = context.Request.Headers.Get("X_FILE_SIZE");
bool ok = false;
System.Text.StringBuilder myData = new System.Text.StringBuilder();
myData.Append(buffer);
if(myData.Length == int.Parse(fileSize)){ ok=true; }
}
catch (Exception)
{
throw;
}
}
There is no overload of StringBuilder.Append that takes a byte array, so it will call the StringBuilder.Append(object) method. That will call ToString on the byte array to get a string value, which results in the string "System.Byte[]".
To get the byte array as a string, you need to know what the bytes represent. For example, if the bytes are text that is encoded as UTF-8 then you can use the Encoding.UTF8 class to decode it:
myData.Append(Encoding.UTF8.GetString(buffer));
Note that multi-byte encodings like UTF-8 may represent one character as multiple bytes, so the string length may be different from the byte array length.