150

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?

0

8 Answers 8

165

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.

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

11 Comments

right, so there´s no way I can upload an image selected from the user just as simply as it sounds...?
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!
I wonder why convert this to a DataURL and not just an object url ?
If you want the synchronous version, you can use: URL.createObjectURL(document.getElementById("fileInput").files[0]);.
@КонстантинВан You must ensure you call URL.revokeObjectURL to prevent memory leaks! developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
|
65

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);
}

1 Comment

Great link! The code you present for the script is not defined though.
21

$('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.

2 Comments

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 store the names of those pairs in an array of objects, iterate through them, and add the event listeners.
20

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);

Comments

7

The easiest way to do it is by creating an Object URL

<input onChanged={(event)=>{ URL.createObjectURL(event!.target!.files[0]) }} />

Comments

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>

2 Comments

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.
I uploaded the executable Flash app here so you can try it out: morearty.com/preview/FileUploadTest.html
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>

Comments

0

For a simple solution using Angular, you can just:

this.imageUrl = URL.createObjectURL(file);
<img [src]="imageUrl" alt="imageUrl"/>

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.