2

I am struggling trying to re-work the idea/code found here (basic premise being working out a file type by simply looking at the first few bytes of data).

Ive got the bare bones of doing what i want - see JSFIDDLE.

Heres my code:

function readTheFiles(file){

            var fileReader = new FileReader();
            fileReader.onloadend = function(e) {
            var fileHeader = new Uint8Array(e.target.result).subarray(0, 4);
            var header = "";
            for (var q = 0; q < fileHeader.length; q++) {
            header += fileHeader[q].toString(16);
            }
            alert(header);
            return header;              
            };
fileReader.readAsArrayBuffer(file);

} 


$("#input-id").on('change', function(event) {
        var files = event.target.files;
        var i = 0;
        for (var i = 0, file; file = files[i]; i++) {

         var headString = readTheFiles(file);
       alert(headString);

        }       
    });   

From what ive read (example 1, example 2) i am sure that the issue lies with calling a callback in the readTheFiles function - presumably the code is calling the alert(headString) line before the files have been loaded (hence why the alert within the readTheFiles function gives the expected result).

Im keen to understand the principal, rather than just get a solution, so any pointers/advice/assistance would be gratefully received.

Many Thanks

Community
  • 1
  • 1
mxp1977
  • 31
  • 1
  • 4
  • `file.type` should already tell you the type of file, is it wrong on your machine? also, i would think `readAsBinaryString`'s result would be easier to compare. – dandavis May 18 '15 at 21:15
  • You can't do that. Read http://blog.slaks.net/2015-01-04/async-method-patterns/ – SLaks May 18 '15 at 21:15
  • @dandavis no it doesn't, it just tells you what type the extension on the file is related to(well on windows anyway, I've tried it on a system where extension doesn't matter). – Musa May 18 '15 at 21:17
  • Very tempted to close as duplicate of http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call – Musa May 18 '15 at 21:20
  • Not provided as dup but for how you can identify a file (also why you should use more than the four first bytes, and also why file.type not always works) https://stackoverflow.com/questions/30232100/get-content-type-of-file-object-using-javascript/30235620#30235620 –  May 18 '15 at 22:03

1 Answers1

1

I am replying to your question about why your alert(headstring) call tells you "undefined". There may be better ways of discovering what type of file you are dealing with.

You are using an asynchronous process. I've modified and commented your code so that you can see what order things are happening in. You'll see that I have created a treat function in the same scope as your on("change", ...) function. Then I've passed this function as an argument to the readTheFiles() function, so that it can be called back later when the file has been read in.

function readTheFiles(file, callback, index){

    var fileReader = new FileReader();

    // 3. This function will be called when readAsArrayBuffer() has
    // finished reading the file 
    fileReader.onloadend = function(e) {
        var fileHeader = new Uint8Array(e.target.result).subarray(0, 4);
        var header = "";
        for (var q = 0; q < fileHeader.length; q++) {
            header += fileHeader[q].toString(16);
        }

        callback(header, index);
    };

    // 2. This gets called almost as soon as fileReader has been created
  fileReader.readAsArrayBuffer(file);
} 


$("#input-id").on('change', function(event) {
    var files = event.target.files;
    var i = 0;
    for (var i = 0, file; file = files[i]; i++) {
      // 1. This is executed for each file that you selected, immediately
      //    after selection. The treat() function is sent as a callback.
      //    It will be called later, when the file has been read in.
      //    Passing `i` as an argument allows you to see which order the
      //    files are treated in.
    var headString = readTheFiles(file, treat, i);
    }

    // 4. This is called by the callback(header) command inside the
    //    readTheFiles() function. The `treat` function was sent to
    //    readTheFiles as the `callback` argument. Putting brackets()
    //    after the function name executes it. Any value put inside
    //    the brackets is sent as an argument to this function.
    function treat(header, index) {
      alert("Header for file " + index + ":" + header);
    }
});   
James Newton
  • 6,623
  • 8
  • 49
  • 113