amazon-web-servicescanvasmeteormeteor-slingshot

Can I convert browser generated image blob to image file for upload?


I'm using fabric.js to dynamically create textures in Threes.js, and I need to save the textures to AWS. I'm using meteor-slingshot, which normally takes images passed in through a file selector input. Here's the uploader:

var uploader = new Slingshot.Upload("myFileUploads");

uploader.send(document.getElementById('input').files[0], function (error, downloadUrl) {
  if (error) {
    console.error('Error uploading', uploader.xhr.response);
    alert (error);
  }
  else {
    Meteor.users.update(Meteor.userId(), {$push: {"profile.files":downloadUrl}});
  }
});

Uploading works fine from the drive ... but I'm generating my files in the browser, not getting them from the drive. Instead, they are generated from a canvas element with the following method:

    generateTex: function(){
        var canvTex         = document.getElementById('texture-generator');
        var canvImg         = canvTex.toDataURL('image/jpeg');
        var imageNew        = document.createElement( 'img' );
        imageNew.src        = canvImg;

    }

This works great as well. If I console.log the imageNew, I get my lovely image with base 64 encoding:

 <img src=​"data:​image/​jpeg;​base64,/​9j/​
4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgID 
//....carries on to 15k or so characters

If I console.log a file object added from the drive via filepicker ( not generated from a canvas ), I can see what the file object should look like:

file{
  lastModified: 1384216556000
  lastModifiedDate: Mon Nov 11 2013 16:35:56 GMT-0800 (PST)
  name: "filename.png"
  size: 3034
  type: "image/png"
  webkitRelativePath: ""
  __proto__: File
}

But I can't create a file from the blob for upload, because there is no place in the file object to add the actual data.

To sum up I can:

  1. Generate an image blob and display it in a dom element
  2. Upload files from the drive using meteor-slingshot
  3. inspect the existing file object

But I don't know how to convert the blob into a named file, so I can pass it to the uploader.

I don't want to download the image, (there are answers for that), I want to upload it. There is a "chrome only" way to do this with the filesystem API but I need something cross browser (and eventually cross platform). If someone could help me with this, I would have uncontainable joy.


Solution

  • Slingshot supports blobs just as well as files: https://github.com/CulturalMe/meteor-slingshot/issues/22

    So when you have a canvas object called canvTex and a Slingshot.Upload instance called uploader, then uploading the canvas image is as easy as:

    canvTex.toBlob(function (blob) {
      uploader.send(blob, function (error, downloadUrl) {
        //...
      });
    });
    

    Because blobs have no names, you must take that into account when defining your directive. Do not attempt to generate a key based on the name of the file.