VGTech is a blog where the developers and devops of Norways most visited website share code and tricks of the trade… Read more



Are you brilliant? We're hiring. Read more

The magic of createObjectURL()

JS

The web platform is maturing faster and faster, and we’re seeing the work normally done by native desktop applications now often shifting towards web-based applications instead. Features that may appear to have little importance can be really powerful when combined together.

A good example of this is URL.createObjectURL(). On it’s own, it really doesn’t do much. Paired with the HTML5 video and audio element, or even the good old image element, it gets to be really powerful.

URL.createObjectURL() is part of the URL-interface, which can be used to construct and parse URLs. URL.createObjectURL() specifically, can be used to create a reference to a File or a Blob. As opposed to a base64-encoded data URL, it doesn’t contain the actual data of the object – instead it holds a reference.

Let’s say you have a page that prompts the user to upload an image. The file input element is, as we all know, very simple and far from user friendly. When a user has selected an image, it would make sense (in a lot of cases) to show a preview of the image. We are now finally able to solve this problem in a simple and intuitive way:

Show code
var fileInput = document.querySelector('input[type="file"]');
var preview = document.getElementById('preview');

fileInput.addEventListener('change', function(e) {
    var url = URL.createObjectURL(e.target.files[0]);  
    preview.setAttribute('src', url);
});

Simple, right? This produces something like the following:

The nice thing about this is that it’s really fast. Previously, we’ve had to instantiate a FileReader instance and read the whole file as a base64 data URL, which takes time and a lot of memory. With createObjectURL(), the result is available straight away, allowing us to do things like reading image data to a canvas or the length of an audio file. Great, right?

One thing to keep in mind is that once you’re done with the generated object URL, you should revoke it. This frees up memory, which is usually handled automatically when you close the page or navigate away from it, but it’s generally a good idea anyway. Revoking the URL is a simple process – just call URL.revokeObjectURL(<objectUrl>) from the onLoad-handler of the element you are using it for.

Read more about createObjectUrl on the Mozilla Developer Network.

Developer at VG with a passion for Node.js, React, PHP and the web platform as a whole. espen.codes - @rexxars


5 comments

  • Torkel Bjørnson-Langen

    Sweet! Thank you for the tip – I will probably use this my self.

    Just one note: If the input[type=file] allows multiple selections then this code will only preview the first. Is it possible to rewrite the querySelector() query to omit elements with the 'multiple' attribute? Or do I have to do it using xpath or javascript? Thanks!


    • Espen Hovlandsdal

      Sure. This was a very contrived example. You could either exclude inputs with the multiple attribute:

      document.querySelector('input[type="file"]:not([multiple])');

      Or, even better, you could generate images on the fly for all images selected. See this JSFiddle for a better example.

  • Frank

    This works great on my local machine, a PC, but it does not on my mobile app created with PhoneGap. Do you if there are setting I need to adjust. The url variable I get looks good. It is blob:file:///497c4.....
    There is no error but also no image displayed. I just copied your code.
    I would appreciate any suggestions.
    Thanks,
    Frank.


  • Frank

    In reference to the above. I also noticed that the preview.onload function is not called on mobile, and on mobile it is "blob:file:///..." and local it is "blob:http://localhost/..." finally on the server it is "blob:http://www.server.com/..."


  • Priyanka

    Thank you ,Clear Explanation


Leave your comment