0

I am using knockout js and I want to post a file. It works on Google Chrome and Firefox, but fails on IE:

file binding handler:

ko.bindingHandlers.file = {
    init: function (element, valueAccessor) {
        $(element).change(function () {
            var file = this.files[0];
            if (ko.isObservable(valueAccessor())) {
                valueAccessor()(file);
            }
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
        var file = ko.utils.unwrapObservable(valueAccessor());
        var bindings = allBindingsAccessor();

        if (bindings.fileObjectURL && ko.isObservable(bindings.fileObjectURL)) {
            var oldUrl = bindings.fileObjectURL();
            if (oldUrl) {
                windowURL.revokeObjectURL(oldUrl);
            }
            bindings.fileObjectURL(file && windowURL.createObjectURL(file));
        }

        if (bindings.fileBinaryData && ko.isObservable(bindings.fileBinaryData)) {
            if (!file) {
                bindings.fileBinaryData(null);
            } else {
                var reader = new FileReader();
                reader.onload = function (e) {
                    bindings.fileBinaryData(e.target.result);
                };
                reader.readAsArrayBuffer(file);
            }
        }
    }
};

Viewmodel:

var windowURL = window.URL || window.webkitURL;

self.fileBinary = ko.observable();

var slotModel = function () {
    var that = {};

    that.imageFile = ko.observable();
    that.imageObjectURL = ko.observable();
    that.imageBinary = ko.observable();

    that.fileSize = ko.computed(function () {
        var file = this.imageFile();
        return file ? file.size : 0;
    }, that);

    that.firstBytes = ko.computed(function () {
        if (that.imageBinary()) {
            var buf = new Uint8Array(that.imageBinary());
            var bytes = [];
            var bytess = [];
            var i;

            for (i = 0; i < buf.length; ++i) {
                bytess.push(buf[i]);
            }
            self.fileBinary(bytess);

            for (i = 0; i < Math.min(10, buf.length); ++i) {
                bytes.push(buf[i]);
            }
            return '[' + bytes.join(', ') + ']';
        } else {
            return '';
        }
    }, that);

    return that;
}; 

View:

<button type="button" data-bind="click: addSlot">
    Add slot</button>
<div data-bind="foreach: { data: images, beforeRemove: beforeRemoveSlot }">
    <div>
        <input type="file" accept="image/*" data-bind="file: imageFile, fileObjectURL: imageObjectURL, fileBinaryData: imageBinary" />
        <div data-bind="if: imageObjectURL">
            <img class="thumb" data-bind="attr: { src: imageObjectURL }" />
        </div>
        <div>
            Size: <span data-bind="text: fileSize"></span>&nbsp;bytes</div>
        <div>
            First 10 bytes: <span data-bind="text: firstBytes"></span>
        </div>
        <button type="button" data-bind="click: $parent.removeSlot">
            Remove</button>
            <button type="button" data-bind="click: $parent.uploadFileContent">
            Upload File</button>
    </div>
</div>

This does not work only on IE. The error message is on this line:

var file = this.files[0];

Files is not defined

Tomalak
  • 332,285
  • 67
  • 532
  • 628
SamirJ
  • 3
  • 1
  • 5

0 Answers0