0

We are building an application where the user can upload images, but I need to resize an image before I can upload them to the server. The input for the file is an input[type=file] and we check if the image is valid. If it is valid, we continue with the following request:

Upload.upload({url: url, data: {file: input.x}, headers: {'Authorization': token}});

The input variable is the value of the input field in the HTML. This codes works great when we don't need to resize the image. Unfortunately, this would only be the case in a perfect world. After a while searching for the same problems, I seem to have found the solution using the following function:

var resize = function(size, url, callback) {
    var temp = new Image();
    temp.onload = function() {
        var target = { width: temp.width, height: temp.height, aspect: temp.width / temp.height };

        if (temp.width > temp.height) {
            size = Math.min(temp.width, size);
            target.width = size; target.height = size / target.aspect;
        } else {
            size = Math.min(temp.height, size);
            target.height = size; target.width = size * target.aspect;
        }

        var canvas = document.createElement('canvas');
        canvas.width = target.width; canvas.height = target.height;

        var ctx = canvas.getContext('2d');
        ctx.drawImage(this, 0, 0, temp.width, temp.height, 0, 0, target.width, target.height);

        callback(canvas.toDataURL(url.split(',')[0].split(':')[1].split(';')[0]));
    }; temp.src = url;
}

This appears to be working great. I need to pass a Base64 string. So I wrapped the upload method inside the following:

var reader = new FileReader();  
reader.onload = function(e) {
    resize(1000, e.target.result, function(done) {
        console.log(done);
        Upload.upload({url: url, data: {file: done}, headers: {'Authorization': UserService.getToken()}});
    });
}
reader.readAsDataURL(file);

This way I pass a Base64 string containing the image and even this seems to be working like a charm. But the biggest problem is, the server expects a real file and not a Base64 string. So the upload itself fails.

I found the function on Convert Data URI to File then append to FormData which should fix this, but it doesn't. I changed the method to this after adding the method from the link:

var reader = new FileReader();  
reader.onload = function(e) {
    resize(1000, e.target.result, function(done) {
        console.log(done);
        Upload.upload({url: url, data: {file: dataURItoBlob(done)}, headers: {'Authorization': UserService.getToken()}});
    });
}
reader.readAsDataURL(file);

Does any of you know how I could change the Base64 string back to a file again? I found tons of post explaining how I could show them in a browser, but none solving my problem to upload it as file.

Community
  • 1
  • 1
Sietse
  • 573
  • 1
  • 5
  • 22

1 Answers1

0

Sorry for the question. But it seems the dataURItoBlob function works fine, but there is was no original filename inside the blob, so I couldn't upload it right away. I changed the resize function so it performs both actions at once and this is the result:

var resize = function(size, url, name, callback) {
    var temp = new Image();
    temp.onload = function() {
        var target = { width: temp.width, height: temp.height, aspect: temp.width / temp.height };

        if (temp.width > temp.height) {
            size = Math.min(temp.width, size);
            target.width = size; target.height = size / target.aspect;
        } else {
            size = Math.min(temp.height, size);
            target.height = size; target.width = size * target.aspect;
        }

        var canvas = document.createElement('canvas');
        canvas.width = target.width; canvas.height = target.height;

        var ctx = canvas.getContext('2d');
        ctx.drawImage(this, 0, 0, temp.width, temp.height, 0, 0, target.width, target.height);

        var type = url.split(',')[0].split(':')[1].split(';')[0];
        var data = canvas.toDataURL(type);

        //callback(data);

        var bytes = (data.split(',')[0].indexOf('base64') >= 0) ? atob(data.split(',')[1]) : unescape(dataURI.split(',')[1]);

        var ia = new Uint8Array(bytes.length);
        for(var i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); }

        var blb = new Blob([ia], {type : type});
        blb.name = name;

        callback(blb);
    }; temp.src = url;
};

To upload the file, I do the following:

var deferred = $q.defer();
var reader = new FileReader();
reader.onload = function(e) {
    resize(maxSize, e.target.result, image.name, function(done) {
        deferred.resolve(Upload.upload({url: url, data: {file: done}, headers: {'Authorization': token}));
    });
}
reader.readAsDataURL(image);

return deferred.promise;
Samer Murad
  • 1,732
  • 22
  • 24
Sietse
  • 573
  • 1
  • 5
  • 22