0

I'm currently trying to implement a new HTML5 driven upload site. Out of security reasons I was usually quite restrictive regarding file types to be uploaded, so usually only ZIP files were accept from the back end. As there seem to be many people around that seem to have difficulties using ZIP, I thought I'd give it a try and do something as follows:

  • Select files to be uploaded
  • Read 4 first bytes of each file to determine if it's a ZIP file (it's not fool proof, but never mind that).
  • Upload ZIP files directly
  • Take all the other files and create a ZIP archive on the fly and upload that newly created archive.

The whole thing works well, except for the file type checking:

//'files' is an array of files retrieved from <input type='file'...for instance
    function checkFileType(files, callback) {
        for (var i = 0; i < files.length; i++) {

            var fileReader = new FileReader();

            fileReader.onloadend = function (e) {
                var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
                var header = "";
                for (var j = 0; j < arr.length; j++) {
                    header += arr[j].toString(16);
                }

                if (header == '504b34')
                    ;
                else
                    callback("something");

            };


            var blob = files[i].slice(0, 4);
            fileReader.readAsArrayBuffer(blob);
        }
    }

I'm using "slice" here to only read the 4 first bytes (in case the file is huge, I don't want to mess up memory). The only thing that troubles me: Because of the slicing I lose the reference to the actual file in the array. I need to remove files that are being detected as ZIP from the array and start uploading them on the fly.

Afterwards, all remaining files in the array shall be zipped. My approach doesn't seem to work because of that missing 'reference'...

1 Answer 1

1

I guess I just found a simple solution, using a closure,...

function checkFileType(files, callback)
{
    for(var i = 0; i < files.length; i++) {
        var blob = files[i].slice(0, 4);
        var fileReader = new FileReader();

        fileReader.onload = (function(file_array, i)
        {
            return function(e) {
                var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
                var header = "";

                for (var j = 0; j < arr.length; j++) {
                    header += arr[j].toString(16);
                }

                if (header == '504b34')
                    callback("ZIP");
                else
                    callback(e.name);
            };
        })(files, i);

        fileReader.readAsArrayBuffer(blob);
        console.log(fileReader.result);
    }
}

Like this, both the reference to the array and the index are available inside the 'onload' callback.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.