0

I'm working on adding images to page, do something with collection of added images (preview etc) and finally I want them save. Everything is cool until the files object is used to show or save the photo.

var input = document.getElementById('files');
var files = input.files;

as it is an array of objects read only - it is impossible to manipulate it freely. For working with that array friendly I maped it like that:

var addedFiles = added(files); 
function added(from) {
    return $.map(from, function (i) {
         var x = { lastModified: i.lastModified, lastModifiedDate: i.lastModifiedDate, name: i.name, size: i.size, type: i.type, webkitRelativePath: i.webkitRelativePath }
         return x;
    });
}

... then do something with those files - and I want to preview, and then save - but for example during preview I get an error:

Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.

    function readImage(file) {
        var reader = new FileReader();
        reader.addEventListener("load", function () {
            var image = new Image();

            image.addEventListener("load", function () {
                preview.innerHTML += drawHtml(this, file);
                window.URL.revokeObjectURL(image.src); //blob version
            }); 
            image.src = reader.result; //file version
            image.src = window.URL.createObjectURL(file) //blob version
        });
        reader.readAsDataURL(file); // here fire the error
    }

When I pass for testing originally file obj to above code every thing is working.

Question: How to create custom obj (in my case array of obj) that can be parse to file obj

P.S. In project I'm using jquery and javascript

szkut
  • 353
  • 2
  • 22
  • Why are you needing to manipulate `input.files`? You're converting the File objects (https://developer.mozilla.org/en-US/docs/Web/API/File) to something else that isn't a file object anymore. Maybe there's a different approach you can take. – Jacob Nov 07 '18 at 00:16
  • 1
    _Maybe_ you could implement the `Blob` interface. That's at least one thing that's missing in your objects: https://developer.mozilla.org/en-US/docs/Web/API/Blob – Jacob Nov 07 '18 at 00:17
  • - before the client sends a picture to the server after adding it, he can add additional informations - during the generation of the preview, I'm using ajax to connect to the database to check if the picture already exists in db - depending on the situation it shows the error that the img already exists every thing before img is saved – szkut Nov 07 '18 at 00:35

2 Answers2

0

Rather than mapping the File objects to new, incompatible objects, you could instead wrap them with the additional things you need, but then use the underlying original files when reading them:

const fileSelections = Array.prototype.map.call(input.files, file => ({
  // This will let you get to the underlying file in the wrapper objects
  file,

  // If you want pass-throughs, you can do stuff like this:
  get lastModified() { return file.lastModified },

  // And you can add your own properties/methods as you please
});

function readImage(fileSelection) {
  // Unwrap the file
  const file = fileSelection.file;

  const reader = new FileReader();
  reader.addEventListener("load", function () {
    const image = new Image();

    image.addEventListener("load", function () {
      preview.innerHTML += drawHtml(this, file);
      window.URL.revokeObjectURL(image.src); //blob version
    }); 
    image.src = reader.result; //file version
    image.src = window.URL.createObjectURL(file) //blob version
  });
  reader.readAsDataURL(file);
}
Jacob
  • 77,566
  • 24
  • 149
  • 228
0

correct answer is blob - it's something amazing for me.

//from is the array of obj - files
  function added(from) {
                    var out = [];
                    for (var i = 0; i < from.length; i++) {
                        (function (obj) {
                            var readerBase64 = new FileReader();
                            var obj = from[i];
                            readerBase64.addEventListener("load", function () {
                                var fileBase64 = readerBase64.result;
                                var row = { name: obj.name, size: obj.size, type: obj.type, base64: fileBase64 }
                                out.push(row);
                            });
                            readerBase64.readAsDataURL(obj); 
                        })(from[i]);
                    }
                    return out;
                }

'out' is a table of my own objects with base64, so I can create images for preview and 'do something functions' in the end I'm going to use base64 for create files.

here link for question related to my next step - creating img from blob (where I'm using additional lib b64toBlob)

szkut
  • 353
  • 2
  • 22