Hi,

This isn't necessarily an Emscripten issue but I thought this was a good 
place for this question since I need to call C from JavaScript through 
Emscripten.

*What I'm trying to do:*
The user should be able to select a WebGL button. The button calls an HTML 
input file which brings up File Explorer to select a file (such as a txt 
file or image). When the user selects a file (including a binary file), the 
contents get sent from JavaScript to C, where C then writes the file to the 
Emscripten local file system directory and where I should be able to send 
the contents of the file over C sockets (this is why I need to be able to 
get binary file contents, because I will be doing things with it in C).

*What I've tried:*
My HTML has an input element:
<input id="file-input" type="file" name="name" style="display: none;"/>

In my C code, when the user presses the WebGL button, I select the 
file-input element to open the file selection:
emscripten_run_script(
        (char*)((std::string)
        "document.getElementById('file-input').click(); " +
        "var fileCont; " +
        "var reader = new FileReader(); " +
        "reader.onloadend = function(evt) { " +
        "   if (evt.target.readyState == FileReader.DONE) { " +
        "       fileCont = evt.target.result; " +
        "   } " +
        "   var arrayBuffer = this.result, " +
        "     array = new Uint32Array(arrayBuffer), " +
        "     binaryString = String.fromCharCode.apply(null, array); " +
        "   Module.ccall('EM_gotOpenFileName', null,  ['string', 'string', 
'number'], [document.getElementById('file-input').value, binaryString, 
arrayBuffer.byteLength]); " +
        "}; " +
        
"reader.readAsArrayBuffer(document.getElementById('file-input').files[0]); "
    ).c_str());

Which then calls my C function where I do stuff with the file content:
extern "C"
{
    EMSCRIPTEN_KEEPALIVE void EM_gotOpenFileName(char* fileName, char* 
cont, int len)
    {
        // Store the file in a temporary location so we can read it later 
if we need to.
        // JavaScript doesn't allow us to grab it's location, so we must do 
it this way.
        std::string tempFile = fileName;

        // Getting the file's name without any directories. i.e 
"C:/fakepath/file.png" will turn into "file.png"
        std::vector<std::string> tkns = findTokens("/", tempFile);
        tempFile = tkns[tkns.size()-1];
        tkns = Operations::findTokens("\\", tempFile);
        tempFile = tkns[tkns.size()-1];
        tempFile = (std::string)".temp/" + tempFile;

        writeFile(tempFile, cont, len); // write the file. assume this 
works fine using fwrite.

        // ...
    }
}

*What's (not) working:*
Text files are writing correctly and being transferred with no problems.
Binary files, such as images, are not. The data written looks different 
than the actual file selected, though they have the same number of bytes.
In JavaScript, I've tried using Uint8Array and Uint16Array. Uint32Array 
errors "Invalid offset/length when creating typed array", and Uint64Array 
doesn't exist.

--

Is there something I am doing wrong, or some other way I should read a file 
(like an image's) contents?
I need to be able to load the data (including binary data from an image) 
into memory that I can do stuff with in C.

Thanks,


-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to