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.
Related
This question already has answers here:
Check image width and height before upload with Javascript
(11 answers)
Closed 1 year ago.
I have an image upload box. Standard stuff:
<input id="image-upload-input" type="file" />
Once the user picks a file, I can access the contents and send it to my API over Axios like such:
const imageUploadInput = document.getElementById("image-upload-input");
const file = imageUploadInput.files[0];
if (!file) {
return;
}
const reader = new FileReader();
const component = this;
reader.onload = function (event) {
axios.post("upload/image", Buffer.from(event.target.result));
};
reader.readAsArrayBuffer(file);
However, I have some restrictions regarding dimensions and would like to check those on the client side.
I am fairly certain it can be done. I haven't tried it yet but I imagine if I just pop the data into an (ideally invisible) img tag with a data src attribute, that might work. Does anyone have any working code? Or a better way to do it?
adding something like this should work
imageUploadInput.onchange = function (event) {
const file = imageUploadInput.files[0];
if (!file) {
return;
}
const image = new Image();
image.onload = function() {
console.log(this.width, this.height);
}
image.src = URL.createObjectURL(file);
};
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 selected a svg file and read it via readDataUrl(<file>), I can set it to an html image element by setting the src to be the value read from the file. However the width and height attributes will be 0. How can I set the value read from a file to an svg element in order to be able to do a getBBox().width to obtain its width?
You can use XMLHttpRequest (or your favourite AJAX library) to read and parse the SVG file. I imagine you can even just pass the dataurl to it if you want.
Edit, because I misread the question :
If you can append the svg to your document, and need to use a FileReader, use its readAsText() method, then insert it in an html element.
function previewFile() {
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onloadend = function () {
var parent = document.getElementById('container');
parent.innerHTML= reader.result;
}
if (file && file.type=="image/svg+xml") {
reader.readAsText(file);
} else {
alert("wrong file type or no file provided");
}
}
<div id="container"></div>
<input type="file" onchange="previewFile()">
If you don't need to use a FileReader (e.g if the file is saved on the server), Paul's answer is better.
If you don't want to actually append the svg file but only know its width/height, you can refer to my
original answer :
I don't think you can get the height from the data url.
As a workaround, you can use the readAsText()method of the fileReader API, combined with the DOMParser() method, in order to read the viewBox property of the svg.
function xlog(msg){
document.getElementById('log').textContent = msg;
}
function previewFile() {
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onloadend = function () {
var doc = new DOMParser().parseFromString(reader.result, 'application/xml');
var viewBox = doc.documentElement.viewBox.baseVal;
xlog('height:'+viewBox.height+' width:'+viewBox.width);
}
if (file && file.type=="image/svg+xml") {
reader.readAsText(file);
} else {
xlog("wrong file type or no file provided");
}
}
<p id="log"></p><br>
<input type="file" onchange="previewFile()">
Note that you can append the doc.documentElement into your document and then get the element's BBox.
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>
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>