I'm creating an app in which I want the user to upload an image with HTML5 <input type="file"/>
I know the browsers restrict getting the path of the image because of security, so i can't copy the image path and put it where ever I want.
Basically I want the user to submit an image, and I want to be able to manipulate the image by setting it as background-image of divs and putting the image in other places. hopefully by changing its source. This is not a server-side app so PHP or any server-side languages aren't an option.
EXAMPLE: If the user clicks a button, the image the user submited can be set as the background-image: url('image-path') of other divs and be applied to to other image tags.
Haven't tested across multiple browsers but can try something like this:
<input type="file" id="file">
$('#file').change(function(evt){
var img = $('<img/>');
var div = $('<div class="with-image"/>');
$(document.body).append(img);
$(document.body).append(div);
var reader = new FileReader();
reader.onload = (function(img) {
return function(ev) {
var image = ev.target.result;
img[0].src = image;
div.css('background-image', 'url("' + image + '")');
};
})(img);
var file = evt.target.files[0];
reader.readAsDataURL(file);
});
Here's a fiddle.
You would want to use the new File API for doing that, and that's really the only way of doing it without a server. Here is an example:
JSFiddle: http://jsfiddle.net/41w6f7n9/
;(function(window, undefined) {
var
doc = window.document,
userFile = doc.getElementById('userFile'),
divPreviews = doc.querySelectorAll('.preview'),
imgPreview = doc.getElementById('img-preview'),
// We will read the file as a Data URL.
fileReader = new FileReader();
var fileutil = {
init: function() {
userFile.addEventListener('change', function(e) {
fileutil.readFile(this.files[0]);
}, false);
},
readFile: function(file) {
var self = this;
// When done reading.
fileReader.onload = function(e) {
if (e.target.readyState === 2) { // 2 means DONE
self.preview(e.target.result);
}
};
// Start reading the file as a Data URL and wait to complete.
fileReader.readAsDataURL(file);
},
preview: function(imageURL) {
imgPreview.src = imageURL;
divPreviews[0].style.backgroundImage = 'url('+imageURL+')';
divPreviews[1].style.backgroundImage = 'url('+imageURL+')';
}
};
fileutil.init();
}(this));
The HTML:
<form>
<input type="file" id="userFile">
</form>
<h1>Image Preview</h1>
<img src="" width="400" id="img-preview">
<h1>Div preview 1</h1>
<div id="preview1" class="preview"></div>
<h1>Div preview 2</h1>
<div id="preview2" class="preview"></div>
Related
I'm building a program that allows the user to choose an image to upload. Once the user chooses one, it triggers the previewFile() function, which uses FileReader to display the image.
Now I'm building a function that will download the same image that the user uploaded (and add some style changes). First, I created a new image element, but now I'm stuck, since I can't figure out how to reference the src value of the original image. Once I do get the src value, I can finish adding the styles, then download the edited image.
Here's what I have so far - can anyone help me out?
HTML:
<input type="file" onchange="previewFile()">
<img src="" alt="Preview File...">
JavaScript:
function previewFile() {
const preview = document.querySelector('img');
const file = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();
reader.addEventListener("load", function () {
preview.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
And the function I need help with:
function createAndDownload() {
const editedImage = document.createElement('img');
/*
Here's where I need help: I need to figure out how to get the image src
from the original image, and set it equal to editedImage.src
*/
//add styles
//download editedImage
}
You assigned it this way:
const preview = document.querySelector('img');
preview.src = reader.result;
So you do the same thing to read it back:
const preview = document.querySelector('img');
const something = preview.src;
I have found code for reading multiple images on the
internet.
Here is the code:
HTML
<input id="browse" type="file" onchange="previewFiles()" multiple>
JavaScript
function previewFiles() {
var preview = document.querySelector('#preview');
var files = document.querySelector('input[type=file]').files;
function readAndPreview(file) {
// Make sure `file.name` matches our extensions criteria
if ( /\.(jpe?g|png|gif)$/i.test(file.name) ) {
var reader = new FileReader();
reader.addEventListener("load", function () {
var image = new Image();
image.height = 100;
image.title = file.name;
image.src = this.result;
preview.appendChild( image );
}, false);
reader.readAsDataURL(file);
}
}
if (files) {
[].forEach.call(files, readAndPreview);
}
}
I have a problem with it, as I do not fully understand what is happening and why it does not preview/seems like it is storing multiple files.
The main problem in the included code is that there is no element with the id preview (ref: var preview = document.querySelector('#preview');)
Adding this and it will work. However, you can skip FileReader as it isn't needed. Instead treat the File as a Blob (they are essentially the same) and use createObjectURL() with it - the performance and the memory footprint are significant better in case you want to display a high amount of images.
document.querySelector('#browse').onchange = function() {
var preview = document.querySelector('#preview');
[].forEach.call(this.files, function(file) {
if (/image\/.*/.test(file.type)) { // use any image format the browser can read
var img = new Image;
img.onload = remURL; // to remove Object-URL after use
img.style.height = "100px"; // use style, "width" defaults to "auto"
img.src = (URL || webkitURL).createObjectURL(file);
preview.appendChild(img); // add image to preview container
}
});
function remURL() {(URL || webkitURL).revokeObjectURL(this.src)}
};
<input id="browse" type="file" multiple>
<div id=preview></div> <!-- an element with this ID was missing -->
Your final lines of code:
if (files) {
[].forEach.call(files, readAndPreview);
}
Should do nothing. It goes for each over an empty array.
I think you were trying to do something like:
files.forEach(readAndPreview)
Which would actually go over all of the files in the files array and call readAndPreview for them.
the main thing that I am trying to do is get this simple image uploader to also allow the user to enter and store a description along with the image that is uploaded. Also some way to clear the images stored once they are in the preview.
What I currently have is
<html>
<body>
<script type='text/javascript'>
function main()
{
var inputFileToLoad = document.createElement("input");
inputFileToLoad.type = "file";
inputFileToLoad.id = "inputFileToLoad";
document.body.appendChild(inputFileToLoad);
var buttonLoadFile = document.createElement("button");
buttonLoadFile.onclick = loadImageFileAsURL;
buttonLoadFile.textContent = "Load Selected File";
document.body.appendChild(buttonLoadFile);
}
function loadImageFileAsURL()
{
var filesSelected = document.getElementById("inputFileToLoad").files;
if (filesSelected.length > 0)
{
var fileToLoad = filesSelected[0];
if (fileToLoad.type.match("image.*"))
{
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent)
{
var imageLoaded = document.createElement("img");
imageLoaded.src = fileLoadedEvent.target.result;
document.body.appendChild(imageLoaded);
};
fileReader.readAsDataURL(fileToLoad);
}
}
}
main();
</script>
</body>
</html>
Any help you can give would be greatly appreciated!
To get a description just create another input element within the form. Your code is not showing how you actually upload the image. So I guess it's a form with a POST action?
To clear the image, just add a button that removes the "img" element. For ease of use, just make the "imageLoaded" global and then remove that from the DOM when pressing that button.
I want to upload a temporary text file say '.json' file on front end.
Then view it in a div element of current window html.
say html body has two div
left div have a form with a upload button to upload a file
and right div displays the content of file after uploading the file
I DO NOT WANT TO MAKE ANY REQUEST TO ANY SERVER.
all i want a front end script to upload a file and display within its tab window
Is that possible? How?
<body>
<input id="File" type="file" />
<input id="Button" type="button" value="button" />
<div id="container"></div>
<script>
var input = document.getElementById('File');
var button = document.getElementById('Button');
var container = document.getElementById('container');
button.onclick = function () {
var reader = new FileReader();
reader.onload = function () {
container.innerHTML = reader.result;
}
input.files.length > 0 && reader.readAsText(input.files[0]);
}
</script>
</body>
Demo Fiddle
Javascript
var files = evt.target.files[0];
var reader = new FileReader();
reader.onload = (function () {
return function (e) {
var span = document.createElement('span');
span.innerHTML = e.target.result;
document.getElementById('output').appendChild(span);
};
})(files);
reader.readAsText(files);
References:
1. HTML5Rocks
2. Firefox MDN
Check the browser support for FileApi
Limitation: This code can show only those files which can be readAsText
Here's an example that uses FileReader.readAsBinaryString.
It comes from an app that allows offline modification of images via the canvas element, without using a server. I find that graphics algorithms are much faster to prototype in JS than C/ASM - platform independence and zero compile-time.
Usually, one has to grab an image from a server (either localhost or a remote one) in order to get past the SameOrigin policy.
Error checking is minimal - i.e, you can select a text/video/whatever file and the code will still attempt to load it and set its contents to be the data used to construct a dataURI for an image element.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
byId('mFileInput').addEventListener('change', onFileChosen, false);
}
// fileVar is an object as returned by <input type='file'>
// imgElem is an <img> element - can be on/off screen (doesn't need to be added to the DOM)
function loadImgFromFile(fileVar, imgElem)
{
var fileReader = new FileReader();
fileReader.onload = onFileLoaded;
fileReader.readAsBinaryString(fileVar);
function onFileLoaded(fileLoadedEvent)
{
var result,data;
data = fileLoadedEvent.target.result;
result = "data:";
result += fileVar.type;
result += ";base64,";
result += btoa(data);
imgElem.src = result;
imgElem.origType = fileVar.type; // unnecessary for loading the image, used by a current project.
}
}
function onFileChosen(evt)
{
if (this.files.length != 0)
{
var tgtImg = byId('tgt');
var curFile = this.files[0];
loadImgFromFile(curFile, tgtImg);
}
}
</script>
<style>
</style>
</head>
<body>
<input id='mFileInput' type='file'/><br>
<img id='tgt' />
</body>
</html>
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?
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.
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);
}
$('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.
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);
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>
The easiest way to do it is by creating an Object URL
<input onChanged={(event)=>{ URL.createObjectURL(event!.target!.files[0]) }} />
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>