9

I am trying to convert an image file captured from an input type=file element without success. Below is my javascript code

        var img = document.getElementById('myimage');
        var file = document.querySelector('input[type=file]').files[0];
        var reader = new FileReader();
        reader.addEventListener("load", function () {
            var theBlob = reader.result;
            theBlob.lastModifiedDate = new Date();
            theBlob.name = file;
            img.src = theBlob;
            var newfile = new File([theBlob], "c:files/myfile.jpg");

        }, false);

        if (file) {
            reader.readAsDataURL(file);
        }

The image is displayed properly in the img element but the File command does not create the myfile.jpg image file. I am trying to capture the image and then resizing it using javascript before I upload it to the server. Anyone know why the image file is not being created? Better yet, anyone have code on how to resize an image file on the client and then upload it to a server?

Dave
  • 873
  • 2
  • 15
  • 27
  • You said the image is displayed properly in the image file. Why not just draw it to canvas and save it as a png or jpg out of the canvas element? Resizing is basically done for you. – YAHsaves May 25 '18 at 23:09
  • Let me know if you would need a full example code of that being done and I'll post it as an answer. – YAHsaves May 25 '18 at 23:11
  • Thanks for your reply. I would appreciate your example code on how to get the jpg image. – Dave May 25 '18 at 23:39

2 Answers2

18

This is how you can get a resized jpeg file from your "myimage" element using Canvas.

I commented every line of code so you could understand what I was doing.

// Set the Width and Height you want your resized image to be
var width = 1920; 
var height = 1080; 


var canvas = document.createElement('canvas');  // Dynamically Create a Canvas Element
canvas.width  = width;  // Set the width of the Canvas
canvas.height = height;  // Set the height of the Canvas
var ctx = canvas.getContext("2d");  // Get the "context" of the canvas 
var img = document.getElementById("myimage");  // The id of your image container
ctx.drawImage(img,0,0,width,height);  // Draw your image to the canvas


var jpegFile = canvas.toDataURL("image/jpeg"); // This will save your image as a 
                                               //jpeg file in the base64 format.

The javascript variable "jpegFile" now contains your image encoded into a URL://Base64 format. Which looks something like this:

// data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...9oADAMBAAIRAxEAPwD/AD/6AP/Z"

You can put that variable as an image source in HTML code and it will display your image in the browser, or you can upload the Base64 encoded string to the server.

Edit: How to convert the file to a blob (binary file) and upload it to the server

// This function is used to convert base64 encoding to mime type (blob)
function base64ToBlob(base64, mime) 
{
    mime = mime || '';
    var sliceSize = 1024;
    var byteChars = window.atob(base64);
    var byteArrays = [];

    for (var offset = 0, len = byteChars.length; offset < len; offset += sliceSize) {
        var slice = byteChars.slice(offset, offset + sliceSize);

        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }

        var byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
    }

    return new Blob(byteArrays, {type: mime});
}

Now clean the base64 up and then pass it into the function above:

var jpegFile64 = jpegFile.replace(/^data:image\/(png|jpeg);base64,/, "");
var jpegBlob = base64ToBlob(jpegFile64, 'image/jpeg');  

Now send the "jpegBlob" with ajax

var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
  // Uploaded.
};

oReq.send(jpegBlob);
YAHsaves
  • 1,697
  • 12
  • 33
  • Thank you for your code. How do I name and then access the jpegFile if I want to upload it to the server? Would it be 'myimage.src' or do I need to create another image file? – Dave May 26 '18 at 00:06
  • @Dave I edited my question to explain how the image file is saved. If however your server will not work with base64 encoding let me know and I'll include code how to convert it to a blob (binary encoding). You can upload it to your server via a simple ajax call, if you need help with that also let me know. – YAHsaves May 26 '18 at 00:18
  • I would need to upload the encoded image to the server. How would I reference the image using a file name? I need to refer to some kind of name, wouldn't I? I plan on uploading using either Ajax or a C# upload file. – Dave May 26 '18 at 00:21
  • I will be processing the file on the server using C# as that is where I will be storing the file path on my msSQL database. So anything you can provide in that context will be very helpful. – Dave May 26 '18 at 00:26
  • @Dave I just edited my answer, hope it helps. I'm a little confused when you mention storing the "file path" on your database. Do you want to upload the path of the image to the server and not the actual image itself? – YAHsaves May 26 '18 at 00:34
  • I want to physically upload the image file itself in its reduced size but I will also be storing the file path on my database so I can access it in my web pages. I just wish I could assign a name to the image file so I could use C# to do the upload. – Dave May 26 '18 at 00:42
  • @Dave The blob file is the image file itself in the same format as it would be stored on your hard drive. You can upload the name as a string var and have c++ join them together. – YAHsaves May 26 '18 at 00:46
  • I guess what I am having a hard time understanding is how to assign a name to the file so I can reference it in javascript and C#. Believe it or not I have been programming for 40 years and I probably get stuck in a rut when I try to analyze something. – Dave May 26 '18 at 00:55
  • I am going to use your code and use ajax to upload the image to a web api written in C#. I can see now that I can arbitrarily add a name along with the image when I send it. I think I finally figured it out. Thanks so much for your help. – Dave May 26 '18 at 01:10
  • @ user3210641 I tried creating a blob from your example and it gave me an error message on the 'var byteChars = window.atob(base64)' command saying that the string to be decoded is correctly encoded. Do you know what caused this error? – Dave May 27 '18 at 00:54
  • I know simple "thank you" comments are discouraged here on SO, but I really just had to say **thank you so freaking much** for this absolute gem of a code snippet! I had been figuratively banging my head against a brick wall for *two days* trying to create the blob as a single array of bytes, before finally finding this answer and realising it needs to be an *array of chunks*! TYVM again :D – Kenny83 Mar 03 '21 at 00:27
8

You can't manipulate hard drive directly from the browser. What you can do though is create a link that can be downloaded.

To do this change your var newfile = new File([theBlob], "c:files/myfile.jpg"); into:

const a = document.createElement('a');
a.setAttribute('download', "some image name");
a.setAttribute('href', theBlob);

a.click();
user3210641
  • 1,565
  • 1
  • 10
  • 14
  • That is really cool! I used your code and it downloads to my Download directory. However, this is a web page that is being processed through a mobile device and I don't know where the file would go on a mobile device. Any suggestions on how to get the file from a mobile device? – Dave May 25 '18 at 23:51
  • Or could I change the 'download' to upload and point to a server location? – Dave May 25 '18 at 23:54
  • Concerning the mobile device support, according to https://caniuse.com/#feat=download Android devices should support it. Not sure where it would get downloaded though. – user3210641 May 26 '18 at 00:00
  • I could put the Ajax call after the download code but I don't know if I can determine the location of the file on a mobile device. Getting into a gray area. – Dave May 26 '18 at 00:09
  • Why do you even need this ? – user3210641 May 26 '18 at 00:27
  • i am trying to upload a file from a mobile device using a web page so I am not using native code, rather I am using html, javascript and C# – Dave May 26 '18 at 00:30
  • But your goal is to upload an image to a server selected from mobile device ? – user3210641 May 26 '18 at 00:31
  • Yes. Upload an image from a mobile device to the server which I can do easily if I didn't want to reduce the size of the file before the upload. That requires javascript – Dave May 26 '18 at 00:48