I am working on this for the past 6 hours, and I am unable to figure this out.
I am trying to create a website, in which I choose a folder of images and I show them in my document. I get the first image to show, and then I get the following error in my console.
Uncaught DOMException: Failed to execute 'readAsDataURL' on 'FileReader': The object is already busy reading Blobs.(…)
I believe the issue is caused due to my for loop because the filereader is asynchronous. But I need to loop through the whole array for this, so what am I doing wrong?
I load the files ("will check to make sure I get only images later"), into an array, and then I read each file one at a time.
Before breaking down my code to functions I did everything in a single function and it works! I included the HTML + the original and current JS code. Thank you for taking the time to see this.
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tiled Image Viewer</title>
<script src="js/tiv.js"></script>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main-wrap">
<form name="uploadForm">
<input id="images" type="file" webkitdirectory mozdirectory directory name="myFiles"
onchange="readAndShowFiles();" multiple/>
<span id="list"></span>
</form>
</div>
</body>
</html>
Javascript Original:
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Have to check that this is an image though
// using the file.name TODO
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(file) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(file);
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
Javascript Current:
function readAndShowFiles() {
console.log("Checkpoint2"); //test
var tiv = new tivAPI();
var array = tiv.getLoadedImages();
tiv.showLoadedImages(array);
}
function tivAPI(){
var imagesarray = new Array();
return{
loadImages: function(){
console.log("Loading Files"); //test
var files = document.getElementById("images").files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Have to check that this is an image though
// using the file.name TODO
}
console.log(files.length); //test
return files;
},
getLoadedImages: function(){
imagesarray = this.loadImages();
console.log("Returning Files"); //test
console.log(imagesarray.length);
return imagesarray;
},
showLoadedImages: function(elem){
console.log("Showing Files"); //test
var files = elem;
var reader = new FileReader();
// Closure to capture the file information.
for (var i = 0; i < files.length; i++) {
var file = files[i];
reader.onload = (function(file) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(file);
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
};
}
The reason why your code fails is that you are using the same reader variable on each subsequent loop iteration.
When Javascript parses your code, what happens is that all variables get moved to the top of the function, so your parsed code looks something like this:
function readAndShowFiles() {
var files = document.getElementById("images").files;
var reader;
var file;
var i;
for (i = 0; i < files.length; i++) {
file = files[i];
reader = new FileReader();
reader.onload = (function(file) {
return function(e) {
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
})(file);
reader.readAsDataURL(file);
}
}
You could avoid this error quite simply by just moving all the logic inside the anonymous function like so:
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (var i = 0; i < files.length; i++) {
// Closure to capture the file information.
(function(file) {
var reader = new FileReader();
reader.onload = function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
// Read in the image file as a data URL.
reader.readAsDataURL(file);
})(files[i]);
}
}
Now you are using a unique reader variable for each file iteration. Note also that this could be simpler if you just did:
array.from(files).forEach(function(file) {
// code
})
Or just used the let variable (that way you will use a different FileReader every time):
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (let i = 0; i < files.length; i++) {
let file = files[i];
let reader = new FileReader();
reader.onload = function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
The for loop could be written easier with es6 leaving you with 2 less variables
function readAndShowFiles() {
var files = document.getElementById("images").files;
for (let file of files) {
let reader = new FileReader();
reader.onload = function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img src="', e.target.result,
'" title="', escape(file.name), '">'
].join('');
document.getElementById('list').insertBefore(span, null);
};
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
}
But if you want it super easy, why not just skip the FileReader altogether and avoid all functions & callbacks with URL.createObjectURL? Using createObjectURL you save CPU de/compiling the file to/from base64:
function showFiles() {
var files = document.getElementById("images").files;
for (let file of files) {
let img = new Image;
img.src = URL.createObjectURL(file);
img.title = file.name;
document.getElementById('list').appendChild(img);
}
}
the Problem occured because I was trying to use the same reader for every image.
Moving var reader = new FileReader();into the loop (ShowLoadedImages function), solved the issue and showed all the images like it was supposed to.
I have a page with four images for the user to select. I want the user to be able to preview each image on the site before upload.
The JavaScript code below works for only one image but I would like it to work for multiple images uploaded via <input type="file">.
What will be the best way to do this?
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#output').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#file-input").change(function () {
readURL(this);
});
Here is jQuery version for you. I think it more simplest thing.
$(function() {
// Multiple images preview in browser
var imagesPreview = function(input, placeToInsertImagePreview) {
if (input.files) {
var filesAmount = input.files.length;
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function(event) {
$($.parseHTML('<img>')).attr('src', event.target.result).appendTo(placeToInsertImagePreview);
}
reader.readAsDataURL(input.files[i]);
}
}
};
$('#gallery-photo-add').on('change', function() {
imagesPreview(this, 'div.gallery');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" multiple id="gallery-photo-add">
<div class="gallery"></div>
Add the multiple attribute to your HTMLInputElement
Add the accept attribute to your HTMLInputElement
To filter your files selection to images only, use accept="image/*", or a comma separated MIME list: accept="image/png, image/jpeg"
Use FileReader.readAsDataURL to get the Base64 string,
or URL.createObjectURL to get the file Blob object
Using FileReader.readAsDataURL
The asynchronous way to read the image data is by using FileReader API and its readAsDataURL method which returns a Base64 String:
const preview = (file) => {
const fr = new FileReader();
fr.onload = () => {
const img = document.createElement("img");
img.src = fr.result; // String Base64
img.alt = file.name;
document.querySelector('#preview').append(img);
};
fr.readAsDataURL(file);
};
document.querySelector("#files").addEventListener("change", (ev) => {
if (!ev.target.files) return; // Do nothing.
[...ev.target.files].forEach(preview);
});
#preview img { max-height: 100px; }
<input id="files" type="file" accept="image/*" multiple>
<div id="preview"></div>
Async strategy:
Due to the asynchronous nature of FileReader, you could implement an async/await strategy:
// DOM utility functions:
const el = (sel, par) => (par || document).querySelector(sel);
const elNew = (tag, props) => Object.assign(document.createElement(tag), props);
// Preview images before upload:
const elFiles = el("#files");
const elPreview = el("#preview");
const previewImage = (props) => elPreview.append(elNew("img", props));
const reader = (file, method = "readAsDataURL") => new Promise((resolve, reject) => {
const fr = new FileReader();
fr.onload = () => resolve({ file, result: fr.result });
fr.onerror = (err) => reject(err);
fr[method](file);
});
const previewImages = async(files) => {
// Remove existing preview images
elPreview.innerHTML = "";
let filesData = [];
try {
// Read all files. Return Array of Promises
const readerPromises = files.map((file) => reader(file));
filesData = await Promise.all(readerPromises);
} catch (err) {
// Notify the user that something went wrong.
elPreview.textContent = "An error occurred while loading images. Try again.";
// In this specific case Promise.all() might be preferred over
// Promise.allSettled(), since it isn't trivial to modify a FileList
// to a subset of files of what the user initially selected.
// Therefore, let's just stash the entire operation.
console.error(err);
return; // Exit function here.
}
// All OK. Preview images:
filesData.forEach(data => {
previewImage({
src: data.result, // Base64 String
alt: data.file.name // File.name String
});
});
};
elFiles.addEventListener("change", (ev) => {
if (!ev.currentTarget.files) return; // Do nothing.
previewImages([...ev.currentTarget.files]);
});
#preview img { max-height: 100px; }
<input id="files" type="file" accept="image/*" multiple>
<div id="preview"></div>
Using URL.createObjectURL
The synchronous way to read the image is by using the URL API and its createObjectURL method which returns a Blob:
const preview = (file) => {
const img = document.createElement("img");
img.src = URL.createObjectURL(file); // Object Blob
img.alt = file.name;
document.querySelector('#preview').append(img);
};
document.querySelector("#files").addEventListener("change", (ev) => {
if (!ev.target.files) return; // Do nothing.
[...ev.target.files].forEach(preview);
});
#preview img { max-height: 120px; }
<input id="files" type="file" accept="image/*" multiple>
<div id="preview"></div>
Although looks much simpler, it has implications on the main thread due to its synchronicity, and requires you to manually use (when possible) URL.revokeObjectURL in order to free up memory:
// Remove unused images from #preview? Consider also using
URL.revokeObjectURL(someImg.src); // Free up memory space
jQuery example:
A jQuery implementation of the above FileReader.readAsDataURL() example:
const preview = (file) => {
const fr = new FileReader();
fr.onload = (ev) => {
$('#preview').append($("<img>", {src: fr.result, alt: file.name}));
};
fr.readAsDataURL(file);
};
$("#files").on("change", (ev) => {
if (!ev.target.files) return; // Do nothing.
[...ev.target.files].forEach(preview);
});
#preview img { max-height: 120px; }
<input id="files" type="file" accept="image/*" multiple>
<div id="preview"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
Additional read:
File API — Using files from web applications (MDN)
readAsDataURL (MDN)
FileReader result (MDN)
Promise.all() (MDN)
Preview Image, get file size, image height and width before upload
Tips:
Besides using the HTMLInputElement attribute accept, if you want to make sure within JavaScript that a file is-of-type, you could:
if (!/\.(jpe?g|png|gif)$/i.test(file.name)) {
// Not a valid image
}
or like:
if (!/^image\//i.test(file.type)) {
// File is not of type Image
}
function previewMultiple(event){
var saida = document.getElementById("adicionafoto");
var quantos = saida.files.length;
for(i = 0; i < quantos; i++){
var urls = URL.createObjectURL(event.target.files[i]);
document.getElementById("galeria").innerHTML += '<img src="'+urls+'">';
}
}
#galeria{
display: flex;
}
#galeria img{
width: 85px;
height: 85px;
border-radius: 10px;
box-shadow: 0 0 8px rgba(0,0,0,0.2);
opacity: 85%;
}
<input type="file" multiple onchange="previewMultiple(event)" id="adicionafoto">
<div id="galeria">
</div>
Just use FileReader.readAsDataURL()
HTML:
<div id='photos-preview'></div>
<input type="file" id="fileupload" multiple (change)="handleFileInput($event.target.files)" />
JS:
function handleFileInput(fileList: FileList) {
const preview = document.getElementById('photos-preview');
Array.from(fileList).forEach((file: File) => {
const reader = new FileReader();
reader.onload = () => {
var image = new Image();
image.src = String(reader.result);
preview.appendChild(image);
}
reader.readAsDataURL(file);
});
}
DEMO
$(function() {
// Multiple images preview in browser
var imagesPreview = function(input, placeToInsertImagePreview) {
if (input.files) {
var filesAmount = input.files.length;
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function(event) {
$($.parseHTML('<img>')).attr('src', event.target.result).appendTo(placeToInsertImagePreview);
}
reader.readAsDataURL(input.files[i]);
}
}
};
$('#gallery-photo-add').on('change', function() {
imagesPreview(this, 'div.gallery');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" multiple id="gallery-photo-add">
<div class="gallery"></div>
function previewImages() {
var preview = document.querySelector('#preview');
if (this.files) {
[].forEach.call(this.files, readAndPreview);
}
function readAndPreview(file) {
// Make sure `file.name` matches our extensions criteria
if (!/\.(jpe?g|png|gif)$/i.test(file.name)) {
return alert(file.name + " is not an image");
} // else...
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);
});
reader.readAsDataURL(file);
}
}
document.querySelector('#file-input').addEventListener("change", previewImages);
<input id="file-input" type="file" multiple>
<div id="preview"></div>
function previewImages() {
var preview = document.querySelector('#preview');
if (this.files) {
[].forEach.call(this.files, readAndPreview);
}
function readAndPreview(file) {
// Make sure `file.name` matches our extensions criteria
if (!/\.(jpe?g|png|gif)$/i.test(file.name)) {
return alert(file.name + " is not an image");
} // else...
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);
});
reader.readAsDataURL(file);
}
}
document.querySelector('#file-input').addEventListener("change", previewImages);
<input id="file-input" type="file" multiple>
<div id="preview"></div>
<script type="text/javascript">
var upcontrol = {
queue : null, // upload queue
now : 0, // current file being uploaded
start : function (files) {
// upcontrol.start() : start upload queue
// WILL ONLY START IF NO EXISTING UPLOAD QUEUE
if (upcontrol.queue==null) {
// VISUAL - DISABLE UPLOAD UNTIL DONE
upcontrol.queue = files;
document.getElementById('uploader').classList.add('disabled');
// PREVIEW UPLOAD IMAGES
upcontrol.preview();*enter code here*
//PROCESS UPLOAD ON CLICK
$('#add_files').on('click', function() {
upcontrol.run();
});
}
},
preview : function() {
//upcontrol.preview() : preview uploading file
if (upcontrol.queue) {
var filesAmount = upcontrol.queue.length;
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function(event) {
var fimg = document.createElement('img')
fimg.src = event.target.result,
fimg.classList = "col-sm-6 col-md-6 col-lg-4 float-left center",
document.getElementById('gallery').appendChild(fimg);
}
reader.readAsDataURL(upcontrol.queue[i]);
}
}
},
run : function () {
// upcontrol.run() : proceed upload file
var xhr = new XMLHttpRequest(),
data = new FormData();
data.append('file-upload', upcontrol.queue[upcontrol.now]);
xhr.open('POST', './lockeroom/func/simple-upload.php', true);
xhr.onload = function (e) {
// SHOW UPLOAD STATUS
var fstat = document.createElement('div'),
txt = upcontrol.queue[upcontrol.now].name + " - ";
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// SERVER RESPONSE
txt += xhr.responseText;
} else {
// ERROR
txt += xhr.statusText;
}
}
fstat.innerHTML = txt;
document.getElementById('upstat').appendChild(fstat);
// UPLOAD NEXT FILE
upcontrol.now++;
if (upcontrol.now < upcontrol.queue.length) {
upcontrol.run();
}
// ALL DONE
else {
upcontrol.now = 0;
upcontrol.queue = null;
document.getElementById('uploader').classList.remove('disabled');
}
};
xhr.send(data);
}
};
window.addEventListener("load", function () {
// IF DRAG-DROP UPLOAD SUPPORTED
if (window.File && window.FileReader && window.FileList && window.Blob) {
/* [THE ELEMENTS] */
var uploader = document.getElementById('uploader');
/* [VISUAL - HIGHLIGHT DROP ZONE ON HOVER] */
uploader.addEventListener("dragenter", function (e) {
e.preventDefault();
e.stopPropagation();
uploader.classList.add('highlight');
});
uploader.addEventListener("dragleave", function (e) {
e.preventDefault();
e.stopPropagation();
uploader.classList.remove('highlight');
});
/* [UPLOAD MECHANICS] */
// STOP THE DEFAULT BROWSER ACTION FROM OPENING THE FILE
uploader.addEventListener("dragover", function (e) {
e.preventDefault();
e.stopPropagation();
});
// ADD OUR OWN UPLOAD ACTION
uploader.addEventListener("drop", function (e) {
e.preventDefault();
e.stopPropagation();
uploader.classList.remove('highlight');
upcontrol.start(e.dataTransfer.files);
});
}
// FALLBACK - HIDE DROP ZONE IF DRAG-DROP UPLOAD NOT SUPPORTED
else {
document.getElementById('uploader').style.display = "none";
}
});
</script>
i used somthing like this and i got the best result and easy to understand.
function appendRows(){
$i++;
var html='';
html+='<div id="remove'+$i+'"><input type="file" name="imagefile[]" accept="image/*" onchange="appendloadFile('+$i+')"><img id="outputshow'+$i+'" height="70px" width="90px"><i onclick="deleteRows('+$i+')" class="fas fa-trash-alt"></i></div>';
$("#appendshow").append(html);
}
function appendloadFile(i){
var appendoutput = document.getElementById('outputshow'+i+'');
appendoutput.src = URL.createObjectURL(event.target.files[0]);
}
https://stackoverflow.com/a/59985954/8784402
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);
$(function() {
// Multiple images preview in browser
var imagesPreview = function(input, placeToInsertImagePreview) {
if (input.files) {
var filesAmount = input.files.length;
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function(event) {
$($.parseHTML('<img>')).attr('src', event.target.result).appendTo(placeToInsertImagePreview);
}
reader.readAsDataURL(input.files[i]);
}
}
};
$('#gallery-photo-add').on('change', function() {
imagesPreview(this, 'div.gallery');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" multiple id="gallery-photo-add">
<div class="gallery">
$(function() {
// Multiple images preview in browser
var imagesPreview = function(input, placeToInsertImagePreview) {
if (input.files) {
var filesAmount = input.files.length;
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function(event) {
$($.parseHTML('<img>')).attr('src', event.target.result).appendTo(placeToInsertImagePreview);
}
reader.readAsDataURL(input.files[i]);
}
}
};
$('#gallery-photo-add').on('change', function() {
imagesPreview(this, 'div.gallery');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" multiple id="gallery-photo-add">
<div class="gallery">
<input type='file' name="image" onchange="preview(this);" multiple="multiple" />
window.preview = function (input){
if(input.files && input.files[0]) {
var reader = new FileReader();
reader.readAsDataURL(input.files[0]);
reader.onload = function(e){
$("#previewImg").append("<img src='" + e.target.result +"'>");
}
}
}
I have a function using file reader to preview image, It works fine in single file.
However I try to achieve multiple files.
My question is how to get input files array, loop files through file reader and append img
Javascript Solution Fiddle DEMO
<input id="files" type="file" multiple="multiple" />
<output id="result" />
Pure JavaScript:
function handleFileSelect(event) {
//Check File API support
if (window.File && window.FileList && window.FileReader) {
var files = event.target.files; //FileList object
var output = document.getElementById("result");
for (var i = 0; i < files.length; i++) {
var file = files[i];
//Only pics
if (!file.type.match('image')) continue;
var picReader = new FileReader();
picReader.addEventListener("load", function (event) {
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" + "title='" + file.name + "'/>";
output.insertBefore(div, null);
});
//Read the image
picReader.readAsDataURL(file);
}
} else {
console.log("Your browser does not support File API");
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
jQuery Solution
jQuery File Input Image Preview Before It Is Uploaded
<form id="form1" runat="server">
<input type='file' id="inputFile" />
<img id="image_upload_preview" src="http://placehold.it/100x100" alt="your image" />
</form>
jQuery:
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#image_upload_preview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#inputFile").change(function () {
readURL(this);
});
Working Fiddle
Javascript
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function (theFile) {
return function (e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('previewImg').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
More details about Files API and reference help for this answer...
Using your code Working Fiddle
HTML
<input type='file' name="image" onchange="preview(this);" multiple="multiple" />
<div id='previewImg'></div>
Javascript
window.preview = function (input) {
if (input.files && input.files[0]) {
$(input.files).each(function () {
var reader = new FileReader();
reader.readAsDataURL(this);
reader.onload = function (e) {
$("#previewImg").append("<img class='thumb' src='" + e.target.result + "'>");
}
});
}
}
Muliple File previewing using Jquery and DataURL
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script language="Javascript">
$(function () {
$("#browse").change(function () {
if (typeof (FileReader) != "undefined") {
var dvPreview = $("#preview");
dvPreview.html("");
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png|.bmp)$/;
$($(this)[0].files).each(function () {
var file = $(this);
if (regex.test(file[0].name.toLowerCase())) {
var reader = new FileReader();
reader.onload = function (e) {
var img = $("<img />");
img.attr("style", "height:100px;width: 100px");
img.attr("src", e.target.result);
dvPreview.append(img);
}
reader.readAsDataURL(file[0]);
} else {
alert(file[0].name + " is not a valid image file.");
dvPreview.html("");
return false;
}
});
} else {
alert("This browser does not support HTML5 FileReader.");
}
});
});
</script>
</html>
I have a web page made by html+javascript which is demo, I want to know how to read a local csv file and read line by line so that I can extract data from the csv file.
Without jQuery:
const $output = document.getElementById('output')
document.getElementById('file').onchange = function() {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(progressEvent) {
// Entire file
const text = this.result;
$output.innerText = text
// By lines
var lines = text.split('\n');
for (var line = 0; line < lines.length; line++) {
console.log(lines[line]);
}
};
reader.readAsText(file);
};
<input type="file" name="file" id="file">
<div id='output'>
...
</div>
Remember to put your javascript code after the file field is rendered.
Using ES6 the javascript becomes a little cleaner
handleFiles(input) {
const file = input.target.files[0];
const reader = new FileReader();
reader.onload = (event) => {
const file = event.target.result;
const allLines = file.split(/\r\n|\n/);
// Reading line by line
allLines.forEach((line) => {
console.log(line);
});
};
reader.onerror = (event) => {
alert(event.target.error.name);
};
reader.readAsText(file);
}
I saw a post How do I read in a local text file with javascript?
I want to add a button to simulate an upload. So my consideration is set a watcher to onclick in onchange processing, is it possible?
Here is jsfiddle
js
function readMultipleFiles(evt) {
//Retrieve all the files from the FileList object
var files = evt.target.files;
if (files) {
for (var i = 0, f; f = files[i]; i++) {
alert(f);
var r = new FileReader();
r.onload = (function (f) {
return function (e) {
var contents = e.target.result;
alert(contents);
};
})(f);
r.readAsText(f);
}
} else {
alert("Failed to load files");
}
}
document.getElementById('fileinput').addEventListener('change', readMultipleFiles, false);
html
<input type="file" id="fileinput" multiple />
Instead of the change handler, add a button and add a click handler
<input type="file" id="fileinput" multiple />
<button id="read">Read</button>
then
jQuery(function ($) {
function readMultipleFiles(input) {
//Retrieve all the files from the FileList object
var files = input.files;
if (files && files.length) {
for (var i = 0, f; f = files[i]; i++) {
var r = new FileReader();
r.onload = (function (f) {
return function (e) {
var contents = e.target.result;
alert(contents);
};
})(f);
r.readAsText(f);
}
} else {
alert("Failed to load files");
}
}
var fileIn = $('#fileinput')[0];
$('#read').click(function () {
readMultipleFiles(fileIn)
})
})
Demo: Fiddle