-1

I'm trying to pass a png file from my server (cpp) to a socket (js) by numbers (each number from -128 to 127 is a range of standard characters in cpp) but if I use the String.fromCharCode() method - this won't work

Output from String.fromCharCode is just different from char conversion on cpp (for negative numbers), are there other methods in js that can help me?..

Code on client (js):

socket.onmessage = function (event) {
                const splitted = event.data.split("|")
                if (splitted[0] === "file -d") {
                    let data = splitted[2].split(",")
                    data = String.fromCharCode(...data)
                    console.log(data)
                    const link = document.createElement("a")
                    const file = new Blob([data], { type: 'application/octet-stream;charset=utf-8' })
                    link.href = URL.createObjectURL(file)
                    link.download = splitted[1]
                    link.click()
                    URL.revokeObjectURL(link.href)
                } else
                    console.log("Received from the server: \"" + event.data + "\"")
            }

Code on server (cpp):

connection->send("file -d|" + "my.png" + "|" + "-119,80,78,71,13,...); // just binary data but char-->int

Code for sending file from client to server (js):

submitFile.onmousedown = function () {
        if (connected === true) {
            let file = fileStorage.files[0]
            let fileBuffer = new ArrayBuffer(0)
            let fileReader = new FileReader()
            fileReader.onloadend = function (event) {
                fileBuffer = event.target.result
                let fileData = new Int8Array(fileBuffer)
                socket.send("file -u|" + file.name + "|" + "./files|" + file.size + "|" + fileData)
            }
            fileReader.readAsArrayBuffer(file)
        } else
            alert("No connection to the server")
    }
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • I'm sure what you're asking makes sense to you, but to us with no context, we're going to need a lot more information. Seeing some code would be a good start to understand exactly how you're providing data to JS from C++, and what the expected and actual outputs are. – Rory McCrossan Jul 18 '23 at 10:42
  • from what i understand its just the negative part... so why not move the scale by 128... so its from 0 to 255 – GreenChicken Jul 18 '23 at 10:44
  • Try to convert your `signed int` to `usigned int` and do the `char` conversion then. All character tables I know of start with 0, not with a negative number. To give a more precise answer: we need code, and example, ... – destructioneer Jul 18 '23 at 10:48
  • Increases by 128 - isnt working, because String.fromCharCode(0...128) - just like on cpp: static_cast(0...128) - so if for all i data[i] +=128 - wont work even for a-z (maybe I'm not explaining well...) – Svyatoslav Kuralenok Jul 18 '23 at 10:51
  • The result of function with converted value is equal to not converted - so it wont work.. – Svyatoslav Kuralenok Jul 18 '23 at 11:08
  • `static_cast(c);` – Eljay Jul 18 '23 at 11:11
  • Here's [an old question](https://stackoverflow.com/questions/5766802/send-and-receive-binary-data-over-web-sockets-in-javascript) with some informative answers. – Pointy Jul 18 '23 at 11:15
  • `static_cast(-119) == 4294967177` and `String.fromCharCode(-119) === String.fromCharCode(4294967177)` - so it has effect – Svyatoslav Kuralenok Jul 18 '23 at 11:16

2 Answers2

0

It seems you are trying to parse file -d execution output. and your output seems to be providing with signed char type formatted as decimal instead of unsigned ones.

In this case, I would emulate a byte underflow to get (0~255) counterpart of the negative part.

// adding n since n is negative and will wrap around
const converted = n < 0 ? 256 + parseInt(n, 10) : parseInt(n, 10);

Also, Please note that String.fromCharCode does not accept array as argument. therefore, should be done like following:

// individually convert character and concatenate with .reduce function
const convertedString = charArray.map(char => String.fromCharCode(char)).reduce((a,b) => a+b);

So, If you implement this workaround in your code, It would look like this:

socket.onmessage = function (event) {
                const splitted = event.data.split("|")
                if (splitted[0] === "file -d") {
                    let data = splitted[2].split(",")
                    data = data
                        .map(n => String.fromCharCode(n < 0 ? 256+parseInt(n, 10) : parseInt(n, 10)))
                        .reduce((a,b) => a+b)
                    console.log(data)
                    const link = document.createElement("a")
                    const file = new Blob([data], { type: 'application/octet-stream;charset=utf-8' })
                    link.href = URL.createObjectURL(file)
                    link.download = splitted[1]
                    link.click()
                    URL.revokeObjectURL(link.href)
                } else
                    console.log("Received from the server: \"" + event.data + "\"")
            }
Alex Park
  • 61
  • 1
  • 3
  • Ty for answering, but unfortunately it doesnt work... I rewrite socket.onmessage() but binary data in png file is differ from source, also downloaded png isnt opening (wrong structure of file) ( – Svyatoslav Kuralenok Jul 18 '23 at 14:04
0

Ok, the solution was quite easy...

socket.onmessage = function (event) {
                const splitted = event.data.split("|")
                if (splitted[0] === "file -d") {
                    let data = new Int8Array(splitted[2].split(","))
                    console.log(data)
                    const link = document.createElement("a")
                    const file = new Blob([data], {type: 'application/octet-stream;charset=utf-8'})
                    link.href = URL.createObjectURL(file)
                    link.download = splitted[1]
                    link.click()
                    URL.revokeObjectURL(link.href)
                } else
                    console.log("Received from the server: \"" + event.data + "\"")
            }

Just cast data to Int8Array and now its working fine..