101

I'm trying to load an image selected by the user through an element.

I added a onchange event handler to the input element like this:

<input type="file" name="picField" id="picField" size="24" onchange="preview_2(this);" alt=""/>

and the preview_2 function is:

var outImage ="imagenFondo";
function preview_2(what){
    globalPic = new Image();
    globalPic.onload = function() {
        document.getElementById(outImage).src = globalPic.src;
    }
    globalPic.src=what.value;
}

where outImage has the id value of the tag where I want the new picture to be loaded.

However, it appears that the onload never happens and it does not load anything to the html.

What should I do?

Andy E
  • 311,406
  • 78
  • 462
  • 440
Valentina
  • 1,013
  • 2
  • 7
  • 4
  • 1
    duplicates https://stackoverflow.com/questions/4459379/preview-an-image-before-it-is-uploaded ? – challet Dec 05 '17 at 13:48

6 Answers6

116

In browsers supporting the File API, you can use the FileReader constructor to read files once they have been selected by the user.

Example

document.getElementById('picField').onchange = function (evt) {
    var tgt = evt.target || window.event.srcElement,
        files = tgt.files;

    // FileReader support
    if (FileReader && files && files.length) {
        var fr = new FileReader();
        fr.onload = function () {
            document.getElementById(outImage).src = fr.result;
        }
        fr.readAsDataURL(files[0]);
    }

    // Not supported
    else {
        // fallback -- perhaps submit the input to an iframe and temporarily store
        // them on the server until the user's session ends.
    }
}

Browser support

  • IE 10
  • Safari 6.0.2
  • Chrome 7
  • Firefox 3.6
  • Opera 12.02

Where the File API is unsupported, you cannot (in most security conscious browsers) get the full path of a file from a file input box, nor can you access the data. The only viable solution would be to submit the form to a hidden iframe and have the file pre-uploaded to the server. Then, when that request completes you could set the src of the image to the location of the uploaded file.

Andy E
  • 311,406
  • 78
  • 462
  • 440
  • right, so there´s no way I can upload an image selected from the user just as simply as it sounds...? – Valentina Sep 28 '10 at 15:24
  • @Valentine: no, it's not as straightforward as you might have hoped for. Very little is in the web development world ;-) – Andy E Sep 28 '10 at 15:26
  • Lol... would it work if: through that I upload the image to the server right away and after that load the image to the html (from the server)? – Valentina Sep 28 '10 at 15:27
  • @Valentina: yes. There may also be other solutions in the form of Flash or Java based file uploaders, but remember that not everyone has these components installed in their browsers. – Andy E Sep 28 '10 at 15:30
  • 1
    yes, I'm looking for x-browser solutions so I think I'll give it a try using the server option. Thank you very much! – Valentina Sep 28 '10 at 15:31
  • 1
    I wonder why convert this to a DataURL and not just an object url ? – ShrekOverflow May 27 '15 at 02:34
  • 6
    If you want the synchronous version, you can use: `URL.createObjectURL(document.getElementById("fileInput").files[0]);`. – Константин Ван Feb 15 '16 at 20:18
  • @valentina While uploading the image to the server as soon as it's selected may make it easier (from the programmer's point of view, certainly not the computer's) to display a preview, in production many users might consider that a violation of privacy. – senox13 Jul 25 '19 at 20:30
  • 1
    @КонстантинВан You must ensure you call `URL.revokeObjectURL` to prevent memory leaks! https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL – Dai Oct 26 '19 at 10:13
54

As iEamin said in his answer, HTML 5 does now support this. The link he gave, http://www.html5rocks.com/en/tutorials/file/dndfiles/ , is excellent. Here is a minimal sample based on the samples at that site, but see that site for more thorough examples.

Add an onchange event listener to your HTML:

<input type="file" onchange="onFileSelected(event)">

Make an image tag with an id (I'm specifying height=200 to make sure the image isn't too huge onscreen):

<img id="myimage" height="200">

Here is the JavaScript of the onchange event listener. It takes the File object that was passed as event.target.files[0], constructs a FileReader to read its contents, and sets up a new event listener to assign the resulting data: URL to the img tag:

function onFileSelected(event) {
  var selectedFile = event.target.files[0];
  var reader = new FileReader();

  var imgtag = document.getElementById("myimage");
  imgtag.title = selectedFile.name;

  reader.onload = function(event) {
    imgtag.src = event.target.result;
  };

  reader.readAsDataURL(selectedFile);
}
Mike Morearty
  • 9,188
  • 5
  • 29
  • 34
16

$('document').ready(function () {
    $("#imgload").change(function () {
        if (this.files && this.files[0]) {
            var reader = new FileReader();
            reader.onload = function (e) {
                $('#imgshow').attr('src', e.target.result);
            }
            reader.readAsDataURL(this.files[0]);
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="imgload" >
<img src="#" id="imgshow" align="left">

That works for me in jQuery.

Christos Lytras
  • 31,296
  • 3
  • 53
  • 82
asghar
  • 371
  • 3
  • 5
  • How to use this in case 'imgload' and 'imgshow' are not defined in advance? Let's say I have 5 pairs of file input and image holder returned from the server, and their respective ids are generated based on some index that is also returned from server's code. – Ivan Jul 31 '20 at 22:23
9

ES2017 Way

// convert file to a base64 url
const readURL = file => {
    return new Promise((res, rej) => {
        const reader = new FileReader();
        reader.onload = e => res(e.target.result);
        reader.onerror = e => rej(e);
        reader.readAsDataURL(file);
    });
};

// for demo
const fileInput = document.createElement('input');
fileInput.type = 'file';
const img = document.createElement('img');
img.attributeStyleMap.set('max-width', '320px');
document.body.appendChild(fileInput);
document.body.appendChild(img);

const preview = async event => {
    const file = event.target.files[0];
    const url = await readURL(file);
    img.src = url;
};

fileInput.addEventListener('change', preview);
nkitku
  • 1,507
  • 15
  • 14
1

Andy E is correct that there is no HTML-based way to do this*; but if you are willing to use Flash, you can do it. The following works reliably on systems that have Flash installed. If your app needs to work on iPhone, then of course you'll need a fallback HTML-based solution.

* (Update 4/22/2013: HTML does now support this, in HTML5. See the other answers.)

Flash uploading also has other advantages -- Flash gives you the ability to show a progress bar as the upload of a large file progresses. (I'm pretty sure that's how Gmail does it, by using Flash behind the scenes, although I may be wrong about that.)

Here is a sample Flex 4 app that allows the user to pick a file, and then displays it:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               creationComplete="init()">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:Button x="10" y="10" label="Choose file..." click="showFilePicker()" />
    <mx:Image id="myImage" x="9" y="44"/>
    <fx:Script>
        <![CDATA[
            private var fr:FileReference = new FileReference();

            // Called when the app starts.
            private function init():void
            {
                // Set up event handlers.
                fr.addEventListener(Event.SELECT, onSelect);
                fr.addEventListener(Event.COMPLETE, onComplete);
            }

            // Called when the user clicks "Choose file..."
            private function showFilePicker():void
            {
                fr.browse();
            }

            // Called when fr.browse() dispatches Event.SELECT to indicate
            // that the user has picked a file.
            private function onSelect(e:Event):void
            {
                fr.load(); // start reading the file
            }

            // Called when fr.load() dispatches Event.COMPLETE to indicate
            // that the file has finished loading.
            private function onComplete(e:Event):void
            {
                myImage.data = fr.data; // load the file's data into the Image
            }
        ]]>
    </fx:Script>
</s:Application>
Mike Morearty
  • 9,188
  • 5
  • 29
  • 34
  • To clarify, for those who are worried about security: Flash doesn't allow you to access ANY local file -- it only allows you to access a local file that has been explicitly, interactively pointed to by the user. This is similar to what HTML does (it lets you upload any explicitly specified file to the server), except that Flash also allows local access in addition to the ability to upload the file. – Mike Morearty Sep 28 '10 at 15:50
  • I uploaded the executable Flash app here so you can try it out: http://www.morearty.com/preview/FileUploadTest.html – Mike Morearty Sep 28 '10 at 15:59
1

var outImage ="imagenFondo";
function preview_2(obj)
{
 if (FileReader)
 {
  var reader = new FileReader();
  reader.readAsDataURL(obj.files[0]);
  reader.onload = function (e) {
  var image=new Image();
  image.src=e.target.result;
  image.onload = function () {
   document.getElementById(outImage).src=image.src;
  };
  }
 }
 else
 {
      // Not supported
 }
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>preview photo</title>
</head>

<body>
<form>
 <input type="file" onChange="preview_2(this);"><br>
 <img id="imagenFondo" style="height: 300px;width: 300px;">
</form>
</body>
</html>