50

How to append blob to input of type file?

<!-- Input of type file -->
<input type="file" name="uploadedFile" id="uploadedFile" accept="image/*"><br>
// I am getting image from webcam and converting it to a blob
function takepicture() {
    canvas.width = width;
    canvas.height = height;
    canvas.getContext('2d').drawImage(video, 0, 1, width, height);
    var data = canvas.toDataURL('image/png');
    var dataURL = canvas.toDataURL();
    var blob = dataURItoBlob(dataURL);
    photo.setAttribute('src', data);
}

function dataURItoBlob(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
        return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
    }

    // How can I append this var blob to "uploadedFile". I want to add this on form submit

GSerg
  • 76,472
  • 17
  • 159
  • 346
Vicky
  • 657
  • 1
  • 8
  • 16
  • Add it to a hidden input? – Stubbies Sep 03 '14 at 12:59
  • 2
    why do you return in the for loop after the first byte? – dandavis Sep 09 '14 at 00:56
  • @kristijan : Try setting 'var blob' in a SESSION variable and post it while submitting the form. – kmario23 Sep 10 '14 at 09:39
  • @mario23 thanks, but the problem was it's not my page ~ so I don't have any access in the backend. I decided to go with node-webkit instead of tideSdk because node-webkit allows attaching files to input elements. – Kristijan Sep 11 '14 at 06:59
  • @Kristijan How did you attach file in node webkit, I would like to do that in my project. can you please elaborate on it? – Andrews Oct 27 '16 at 06:55
  • @Andrews nw.js doesn't 'limit' the input, so you can set the values directly on it: https://github.com/nwjs/nw.js/wiki/Changes-to-dom#setting-value-of-file-input-element – Kristijan Nov 02 '16 at 07:48
  • check this answer: https://stackoverflow.com/a/47172409/771379 – dikirill Oct 14 '20 at 22:29

4 Answers4

54

It is possible to set value of <input type="file">.

To do this you create File object from blob and new DataTransfer object:

let file = new File([data], "img.jpg",{type:"image/jpeg", lastModified:new Date().getTime()});
let container = new DataTransfer();

Then you add file to container thus populating its 'files' property, which can be assigned to 'files' property of file input:

container.items.add(file);
fileInputElement.files = container.files;

Here is a fiddle with output, showing that file is correctly placed into input. The file is also passed correctly to server on form submit. This works at least on Chrome 88.

If you need to pass multiple files to input you can just call container.items.add multiple times. So you can add files to input by keeping track of them separately and overwriting its 'files' property as long as this input contains only generated files (meaning not selected by user). This can be useful for image preprocessing, generating complex files from several simple ones (e.g. pdf from several images), etc.

API references:

Kartearis
  • 785
  • 6
  • 6
  • 2
    Hi @Kartearis, for this dataTransfer files method is not usable in any Ios device. Do you have any alternative solution to pass this blob to the input type=file? – Cracker Rex Sep 21 '21 at 04:41
  • 1
    In my case, I needed to trigger the input `change` event in order for the file to be applied: `fileInputElement.dispatchEvent(new Event('change', { 'bubbles': true }))` – Gleb Ignatev Jul 10 '22 at 16:13
9

I had a similar problem with a fairly complex form in an angular app, so instead of the form I just sent the blob individually using XMLHttpRequest(). This particular "blob" was created in a WebAudioAPI context, creating an audio track in the user's browser.

var xhr = new XMLHttpRequest();
xhr.open('POST', 'someURLForTheUpload', true); //my url had the ID of the item that the blob corresponded to
xhr.responseType = 'Blob';
xhr.setRequestHeader("x-csrf-token",csrf); //if you are doing CSRF stuff
xhr.onload = function(e) { /*irrelevant code*/ };
xhr.send(blob);
MikeSmithDev
  • 15,731
  • 4
  • 58
  • 89
  • I process the POST in node.js and can include that code too if needed. I tried using the form and `FormData` object and this is the only way the worked for me. – MikeSmithDev Sep 03 '14 at 18:37
  • Hi Mike, I went in the end with node-webkit as it solves all my issues (it allows attaching files to the inputs) but if I didn't find that I would for sure go with xrh as it's the most elegant solution. – Kristijan Sep 11 '14 at 07:00
  • 4
    This does not answer the question – phil294 Apr 04 '20 at 11:48
  • 1
    @phil294 The question was "How to append blob to input of type file" but the actual problem to solve was how to get that blob to your server. You'll note in the other answer (which didn't work for OP), I mentioned how I took another approach -- to which the OP stated they were also trying that method with no success and that "anything is welcome." That is the reason I posted my solution. – MikeSmithDev Apr 07 '20 at 12:36
7

You can't change the file input but you can use a hidden input to pass data. ex.:

var hidden_elem = document.getElementById("hidden");
hidden_elem.value = blob;
Stubbies
  • 3,054
  • 1
  • 24
  • 33
  • I'm making a bot - so I have no control over the form (it's all legal, we just need to speed up our workflow :D), I don't believe this will be recognized as a file on the end server, that's why I'm trying to find a way to attach it. I'm using TideSDK which gives me access to the iframe and it's content so I'm trying now with blob data (which is currently a hell to inspect, attach and check) – Kristijan Sep 03 '14 at 13:24
  • @Kristijan does it necessarily need to be part of the form? I've done something similar just doing an XHR post sending the blob. – MikeSmithDev Sep 03 '14 at 14:38
  • Well, that's what I'm trying now (not really going well) - but anything is welcome :) I'm even thinking about using formdata – Kristijan Sep 03 '14 at 14:48
  • I went away from TideSDK to node-webkit - which allows attaching files to the input form (of any website) – Kristijan Sep 07 '14 at 13:29
  • @Evervald How does this work the browser convert the FileObject to a string. – Ratatouille Feb 26 '18 at 09:52
  • Note that, the blob object needs to be converted to data url in order for this to work. I'd been trying the same thing on another script and stumbled into this discussion which might be helpful for those who are stuck with uploading images (turned into blob after some operations) with normal form submission (no Ajax): https://github.com/fengyuanchen/cropper/issues/591 – yenren Mar 12 '20 at 06:26
2

I had take too much time to find how to do "url, blob to input -> preview" so I had do a example you can check here https://stackoverflow.com/a/70485949/6443916 https://vulieumang.github.io/vuhocjs/file2input-input2file/

image bonus enter image description here