Does 'fetch' method present the same functionality as 'FileReader'?

Viewed 1332

I managed to read the text file byte by byte and to change the charset from windows-1251 to Unicode for a file loaded from the end user's computer via an input element and FileReader. Now I want to do the same thing for a file from my server, via fetch. Is it possible to do that? (The fetch would be in a page served via HTTP and the URL would be relative, e.g. fetch("raw/graph_tab.txt") — I'm not trying to read a file directly from the end user's machine as I was with an input field and FileReader).

Chunks of working code ('windows-1251.js' library is created by Mathias Bynens):

<input type="file" id="file"/>
<script type="text/javascript">
        document.getElementById("file").addEventListener("change", readFile, false);

        function readFile (evt) {
            var files = evt.target.files;
            var file = files[0];           
            var reader = new FileReader();
            reader.onload = function(event) {
                console.log(windows1251.decode(event.target.result));            
            }};
2 Answers

If you mean you want to have the encoding parameter of the FileReader.readAsText(Blob, encoding) method, then you'd set a charset parameter in the Content-Type header of your response.

If this is not doable for whatever reason, then you'd have to consume your Response object to a Blob using its Body.blob() method, and then pass the resulting Blob to a FileReader.

Otherwise, no, even though the Response object has similar methods than the ones of a FileReader, the text() method doesn't provide an encoding option...

You shouldn't have to do this conversion at all: You're running a web server, which apparently isn't correctly identifying the encoding of the file. It should correctly identify it in the Content-Type header it returns (e.g.: Content-Type: text/plain; charset=windows-1251). See this article by SO's own Joel Spolsky for more information.

If you can't do that for some reason: You can read the file as binary and get an ArrayBuffer for it via arrayBuffer on the fetch response:

fetch("raw/graph_tab.txt")
.then(response => {
    if (!response.ok) {
        throw new Error(response.status);
    }
    return response.arrayBuffer();
})
.then(buffer => {
    // ...convert it here...
})
.catch(error => {
    // Handle/report error
});

So then the question is what we do for ...convert it here.... :-) The library you're referring to expects to get a "byte string" which I'm guessing is the same as what you'd get from the readAsBinaryString method of FileReader. If so, you can convert the ArrayBuffer to that format like this:

const str = new Uint8Array(buffer).map(byte => String.fromCharCode(byte)).join("");

So:

fetch("raw/graph_tab.txt")
.then(response => {
    if (!response.ok) {
        throw new Error(response.status);
    }
    return response.arrayBuffer();
})
.then(buffer => {
    const str = new Uint8Array(buffer).map(byte => String.fromCharCode(byte)).join("");
    console.log(windows1251.decode(str));
})
.catch(error => {
    // Handle/report error
});
Related