1

I understand the current common technique for creating an <img /> element in JavaScript from a client-side File object goes something like this.

(The File object would originate from a file drag-and-drop handler or <input type="file" /> change event.)

function showImageFile( file: File ): void {

    let rdr = new FileReader();
    rdr.readAsDataURL( file );
    rdr.onloadend = function() {
        let img = document.createElement('img');
        img.src = rdr.result;
        document.body.appendChild( img );
    };
}

I don't like this - the notion of serialising what could be a multi-megabyte image to a base64-encoded string (thus using 1.3x more memory on top of the existing File object) as well as incurring the cost of deserializing the string back into the <img /> element - ultimately this will cause at least 3 instances of the image's data to exist in memory. This seems very wasteful and inefficient to me, and JavaScript applications already have a bad rep for excessive memory consumption.

I noticed that for the <video> and <audio> elements (HTMLMediaElement) that MDN recommends doing something like this:

function showVideoFile( file: File ): void {

    let video = document.createElement('video');
    video.srcObject = URL.createObjectURL( file ); // createObjectURL creates a URI alias to the existing file instance in-memory
}

(with the caveat that if srcObject is ever replaced or the video element removed, the previous objectURL must be manually released using revokeObjectURL.

Is there any way to do the same thing for <img />? (I don't see a srcObject property on HTMLImageElement and HTMLImageElement does not derive from HTMLMediaElement). Searching online for "javascript image files without data URIs" unfortunately only returns pages about readAsDataURL which is the opposite of what I want.

2 Answers 2

3

You set its… src.

document.getElementById('file').onchange = function () {
    if (this.files.length !== 0) {
        var img = new Image();
        img.src = URL.createObjectURL(this.files[0]);
        document.body.appendChild(img);
    }
};
<input type="file" id="file" accept="image/*" />

Sign up to request clarification or add additional context in comments.

Comments

0

After sacrificing more minutes down dark and dirty information mines at Google I found a nugget of coal in this December 2014 article http://bytes.schibsted.com/the-magic-of-createobjecturl/ that says that the HTMLImageElement's src attribute does actually accept an object URI (phew!)

MDN also cover it on their website, albeit buried somewhat: https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#Example_Using_object_URLs_to_display_images

In short, my showImageFile function can be updated like so:

function showImageFile( file: File ): void {

    let objectURI = URL.createObjectURL( file ); // looks like "blob:http://mywebsite/{guid}"

    let img = document.createElement('img');
    img.src = objectURI ;
    document.body.appendChild( img );
}

Or if the img element will be reused:

var img: HTMLImageElement;

function showImageFile( file: File ): void {

    let oldSrc = img.src;

    let objectURI = URL.createObjectURL( file );

    img.src = objectURI;

    if( oldSrc ) URL.revokeObjectURL( oldSrc );
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.