96

DataTransferItemList.add allows you to override copy operation in javascript. It, however, only accepts File object.

Copy event

The code in my copy event:

var items = (event.clipboardData || event.originalEvent.clipboardData);
var files = items.items || items.files;

if(files) {
  var blob = Blob.fromDataURL(_this.editor.selection.getSelectedImage().toDataURL("image/png"));
  files.add(blob);
}

The error in chrome:

Uncaught TypeError: Failed to execute add on DataTransferItemList: parameter 1 is not of type File.

Trying the new File(Blob blob, DOMString name)

In Google Chrome I tried this, according to the current specification:

var blob = Blob.fromDataURL(_this.editor.selection.getSelectedImage().toDataURL("image/png"));  
var file = new File(blob, "image.png");

Problem here is, that Google Chrome doesn't stick to specifications very much.

Uncaught TypeError: Failed to construct File: Illegal constructor

Neither does Firefox in this case:

The method parameter is missing or invalid.

Trying the new File([Mixed blobParts], DOMString name, BlobPropertyBag options)

Solution suggested by @apsillers doesn't work too. This is non stadard method used (but useless) in both Firefox and Chrome.

Binary data

I tried to avoid blob, but the file constructor failed anyway:

  //Canvas to binary
  var data = atob(   //atob (array to binary) converts base64 string to binary string
    _this.editor.selection.getSelectedImage()  //Canvas
    .toDataURL("image/png")                    //Base64 URI
    .split(',')[1]                             //Base64 code
  );
  var file = new File([data], "image.png", {type:"image/png"}); //ERROR

You can try that in console:

Chrome <38:
google chrome is retarded Chrome >=38:
google chrome not retarded anymore Firefox: firefox firebug fileAPI

Blob

Passing Blob is probably correct and works in Firefox:

var file = new File([new Blob()], "image.png", {type:"image/png"});

Firefox:
Firefox firebug
Chrome <38:
google chrome is retarded
Chrome >=38:
google chrome not retarded anymore

  • Q: So how can I make File from Blob?

Note: I added more screenshots after @apsillers reminded me to update Google Chrome.

Community
  • 1
  • 1
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • 1
    Look like both Chrome and FF use a non-standard syntax, similar to the `Blob` constructor: [`new File(["

    Hello world!

    "], "hello.html", { type: "text/html" });`](https://code.google.com/p/chromium/issues/detail?id=164933#c7)
    – apsillers Dec 02 '14 at 14:51
  • Any idea how should I turn Blob into valid first argument? – Tomáš Zato Dec 02 '14 at 14:52
  • Read the Blob into a string with a [`FileReader`](http://blog.teamtreehouse.com/reading-files-using-the-html5-filereader-api), I guess. – apsillers Dec 02 '14 at 14:54
  • @apsillers binary data doesn't work. Nothing works actually. They probably didn't even implement it. – Tomáš Zato Dec 02 '14 at 15:17
  • 2
    With your `atob` approach, what error do you see? I don't see any errors in Chrome with `c=document.createElement("canvas"); new File([atob(c.toDataURL("image/png").split(",")[1])], "foo.png", {type:"image/png"});` I've also tested with a non-blank canvas as well. – apsillers Dec 02 '14 at 15:26
  • What version of Chrome are you using? According to a developer's reply in the bug report I linked, the `File` constructor isn't supported until v38. – apsillers Dec 02 '14 at 16:39
  • @apsillers Yes, thank you. After updating the google chrome, everything is fine. – Tomáš Zato Dec 02 '14 at 16:47
  • Does this answer your question? [How to convert Blob to File in JavaScript](https://stackoverflow.com/questions/27159179/how-to-convert-blob-to-file-in-javascript) – S.Saderi Oct 21 '20 at 07:16
  • @TomášZato did you find a solution yet? I have a similar problem in react – user10033434 Dec 31 '22 at 15:44

3 Answers3

199

The File constructor (as well as the Blob constructor) takes an array of parts. A part doesn't have to be a DOMString. It can also be a Blob, File, or a typed array. You can easily build a File out of a Blob like this:

new File([blob], "filename")
Soviut
  • 88,194
  • 49
  • 192
  • 260
pwnall
  • 6,634
  • 2
  • 23
  • 30
  • Where did I say the spec is useless? And where does [specification](http://www.w3.org/TR/FileAPI/#file) state that the first argument of constructor is an array? – Tomáš Zato Dec 02 '14 at 19:56
  • 1
    "This is non stadard method used (but useless)" -- seems to imply that the implementation is useless. You referenced the File API TR, but browser implementations generally reference the ED. You can access it by clicking on the "Latest Editor’s Draft" link. I hope this helps. – pwnall Dec 03 '14 at 00:37
  • What's the difference between TR and ED? Which one should I prefer when actually using the documentation to create scripts? – Tomáš Zato Dec 03 '14 at 03:03
  • 3
    Browser implementors always use the ED. The downside of using the ED is that some/most browsers might be behind. In general, using the TR should be fine. The File API TR is really old (1 year behind the ED), in general they catch up much faster. I think that in most cases Chromium doesn't ship APIs until their specs reach TR. In this case, Firefox really wanted the File constructor for Firefox OS, so they shipped it. The ED documents changes that they asked for (which are good, btw). Since Firefox shipped, I considered that it's OK to also ship the constructor in Chromium. – pwnall Dec 03 '14 at 05:21
  • 1
    The TL;DR is that the standardization process is a bit confusing, and using bleeding-edge features means that you'll have to do a non-trivial amount of digging around. Sorry :( – pwnall Dec 03 '14 at 05:23
  • 2
    Thanks for sympathising with me :). You wouldn't believe how much digging around am I doing without any results. I'm used to this with other languages, but with javascript it's for the first time. – Tomáš Zato Dec 03 '14 at 05:26
  • 2
    Sorry for picking on you earlier, then! I read your bug description on Chromium's bug tracker and got a bit ticked off. Good luck with your code! – pwnall Dec 03 '14 at 06:43
  • So, at the end of the day, what would be the correct syntax to create an instance of File containing a PNG image out of Canvas? – Meglio Aug 26 '19 at 06:56
22

This was the complete syntax which I had to use to convert a blob into a file, which I later had to save to a folder using my server.

var file = new File([blob], "my_image.png",{type:"image/png", lastModified:new Date().getTime()})
Dan
  • 53
  • 1
  • 6
7

this works with me, from canvas to File [or Blob], with filename!

var dataUrl = canvas.toDataURL('image/jpeg');
var bytes = dataUrl.split(',')[0].indexOf('base64') >= 0 ?
          atob(dataUrl.split(',')[1]) :
          (<any>window).unescape(dataUrl.split(',')[1]);
var mime = dataUrl.split(',')[0].split(':')[1].split(';')[0];
var max = bytes.length;
var ia = new Uint8Array(max);
for (var i = 0; i < max; i++) {
  ia[i] = bytes.charCodeAt(i);
}

var newImageFileFromCanvas = new File([ia], 'fileName.jpg', { type: mime });

Or if you want a blob

var blob = new Blob([ia], { type: mime });
Giulio Caccin
  • 2,962
  • 6
  • 36
  • 57
Arttu Pakarinen
  • 101
  • 1
  • 4