1

First of all JS is not my usual language, sorry if the question is not very clear.

I have been testing a code to compress the images that users upload to an <input> the JS code of compression is working perfectly but I don't know how to do to replace the file that they have chosen in the "input" by the one that I have just generated compressed.

I want to do this because the <input> is inside a form so I can upload the image to the server compressed.

Here is the JS fot compression:

const MAX_WIDTH = 300;
const MAX_HEIGHT = 200;
const MIME_TYPE = "image/jpeg";
const QUALITY = 0.8;
const input = document.getElementById("img-1");

input.onchange = function (ev) {
    const file = ev.target.files[0]; // get the file
    const blobURL = URL.createObjectURL(file);
    const img = new Image();
    img.src = blobURL;
    img.onerror = function () {
        URL.revokeObjectURL(this.src);
        // Handle the failure properly
        console.log("Cannot load image");
    };
    img.onload = function () {
        URL.revokeObjectURL(this.src);
        const [newWidth, newHeight] = calculateSize(img, MAX_WIDTH, MAX_HEIGHT);
        const canvas = document.createElement("canvas");
        canvas.width = newWidth;
        canvas.height = newHeight;
        const ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0, newWidth, newHeight);
        canvas.toBlob(
            blob => {
                // Do something with img in my case show in Frontend
                displayInfo('Original file', file);
                displayInfo('Compressed file', blob);
            },
            MIME_TYPE,
            QUALITY);

        // Only for testing and see results
        document.getElementById("pruebas-tam").append(canvas);
    };
};
Pablo
  • 364
  • 1
  • 10
  • 1
    Is your `` an ` – freedomn-m Feb 08 '22 at 15:50
  • 2
    See https://stackoverflow.com/a/1696891/12780866 – stacj Feb 08 '22 at 16:01
  • Exactly, I had read that, but I don't want to choose the file, I just want to change the one he has uploaded for the same one but compressed. – Pablo Feb 08 '22 at 16:03
  • 1
    You can rebuild the form data in Submit, such that you upload your new file data versus the File in the Input. See https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData – Twisty Feb 08 '22 at 16:03
  • @Twisty It seems like a viable option, but I am surprised that a problem that must be quite common does not have a standard solution. I will try your recomendation, thanks! – Pablo Feb 08 '22 at 16:09

1 Answers1

1

After many tests I managed to find the solution, adding these lines just where we have the 'blob' we can replace the input with the new compressed image. The solution is based on creating a file using the Blob and then assigning it to a DataTransfer and finally assigning it back to the Input.

displayInfo('Original file', file);
displayInfo('Compressed file', blob);

// Here is where we convert the blob into a file and put inside DataTransfer
let newfile = new File([blob], "filename.ext",{type:MIME_TYPE, 
lastModified:new Date().getTime()});
let container = new DataTransfer();
container.items.add(newfile);
input.files = container.files;
Pablo
  • 364
  • 1
  • 10