I'm using a multiple file input and then a for loop to iterate through the files using FileReader. JSfiddle here: https://jsfiddle.net/zLq8rsos/. It shows filename en contents correctly, but I don't understand why the counting doesn't work. If I choose one file, it's numbered '1' (why not 0?). If I choose two files, they're both counted '2'. What am I doing wrong?
function showDetails(file, content, n) {
var start = content.substring(0, 9);
var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
$('#results').append(message);
}
$(document).ready(function() {
$('#files').on('change', function(evt) {
var files = evt.target.files;
if (files) {
$('#results').text("");
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
var content = e.target.result;
showDetails(theFile, content, i);
};
})(f);
reader.readAsText(f, "UTF-8");
}
} else {
console.log("Failed to load file(s)");
};
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="files" name="files[]" multiple>
<div id="results">
</div>
Use closures Modify IIFE
function showDetails(file, content, n) {
var start = content.substring(0, 9);
var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
$('#results').append(message);
}
$(document).ready(function() {
$('#files').on('change', function(evt) {
var files = evt.target.files;
if (files) {
$('#results').text("");
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.onload = (function(theFile,count) {
return function(e) {
var content = e.target.result;
showDetails(theFile, content, count);
};
})(f,i+1);
reader.readAsText(f, "UTF-8");
}
} else {
console.log("Failed to load file(s)");
};
});
});
Problem Statement - In for loop when you are trying to access the value of i, it has already completed the iterations and hence the value because 1 for 1 file and 2 for 2 files.
You can update your for loop to
for (var i = 0, f; f = files[i]; i++) {
(function(i){ // Added
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
var content = e.target.result;
showDetails(theFile, content, i);
};
})(f);
reader.readAsText(f, "UTF-8");
})(i+1);
}
For reference - https://jsfiddle.net/zLq8rsos/1/
JSFIDDLE
All you need is to update the count through loop each time
function showDetails(file, content, n) {
var start = content.substring(0, 9);
var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
$('#results').append(message);
}
$(document).ready(function() {
$('#files').on('change', function(evt) {
var files = evt.target.files;
if (files) {
$('#results').text("");
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
var x=1;
reader.onload = (function(theFile) {
return function(e) {
var content = e.target.result;
showDetails(theFile, content, x);
x++;
};
})(f);
reader.readAsText(f, "UTF-8");
}
} else {
console.log("Failed to load file(s)");
};
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="files" name="files[]" multiple>
<div id="results">
</div>
Use jquery each, the index of the file start with 0
function showDetails(file, content, n) {
var start = content.substring(0, 9);
var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
$('#results').append(message);
}
$(document).ready(function() {
$('#files').on('change', function(evt) {
var files = evt.target.files;
if (files) {
$('#results').text("");
$.each(files, function(i, f){
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
var content = e.target.result;
showDetails(theFile, content, i);
};
})(f);
reader.readAsText(f, "UTF-8");
});
} else {
console.log("Failed to load file(s)");
};
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="files" name="files[]" multiple>
<div id="results">
</div>
Related
I made a file uploader that handles images, but it doesn't work well with files.
For example: if I upload 3 xlsx/word or any files, these will have the same name for each.
My code is here:
<form>
<input id="files" type="file" multiple="multiple">
<div id="result"></div>
</form>
function handleFileSelect(event) {
if (window.File && window.FileList && window.FileReader) {
var files = Array.from(event.target.files);
var output = document.getElementById("result");
output.innerHTML = '';
console.log(files);
for (var i = 0; i < files.length; i++) {
var file = files[i];
if(file.type.match('.php')){
alert('ERROR');
continue;
}
var picReader = new FileReader();
picReader.addEventListener("load", function (event) {
var picFile = event.target;
var div = document.createElement("div");
div.className = "col-6 col-sm-4 p-1";
if (file.type.match('image')) {
div.innerHTML = "<img src='" + picFile.result + "'" + "title='" + file.name + "'/>";
}else{
div.innerHTML = "<div class='upload-thumb'>" + file.name + "</div>";
}
output.insertBefore(div, null);
});
picReader.readAsDataURL(file);
}
} else {
console.log("Your browser does not support File API");
}
}
Link:
https://jsfiddle.net/laszlooo/7c1Lv5x2/
Thank You!
Problem you have is you have the infamous for loop bug. Where the reference to i updates as your loop executes. You can either use let instead of var or break out the part you read the file into a function so you do not have the issue.
function readFile(file, output) {
var picReader = new FileReader();
picReader.addEventListener("load", function(event) {
var picFile = event.target;
var div = document.createElement("div");
div.className = "col-6 col-sm-4 p-1";
if (file.type.match('image')) {
div.innerHTML = "<img src='" + picFile.result + "'" + "title='" + file.name + "'/>";
} else {
div.innerHTML = "<div class='upload-thumb'>" + file.name + "</div>";
}
output.insertBefore(div, null);
});
picReader.readAsDataURL(file);
}
function handleFileSelect(event) {
if (window.File && window.FileList && window.FileReader) {
var files = Array.from(event.target.files);
var output = document.getElementById("result");
output.innerHTML = '';
console.log(files);
for (var i = 0; i < files.length; i++) { // <-- where the problem begins
var file = files[i]; // <-- this is your problem with the reference
if (file.type.match('.php')) {
alert('ERROR');
continue;
}
readFile(file, output) // <-- using a function gets around the reference issue
}
} else {
console.log("Your browser does not support File API");
}
}
document.querySelector("input").addEventListener("change", handleFileSelect)
<form>
<input id="files" type="file" multiple="multiple">
<div id="result"></div>
</form>
I have just javascript and css. But want to show the uploaded file name
Googled a lot
So I have this as css:
.metadata .filename{
font-size: 10px;
color: red;
display: inline-block;
}
and this is the js code:
var messagetext = '';
messagetext += '<span class="metadata">' + '<span class="filename">' + file.name + '</span>';
But if I do a console.log(file.name) then I see the name of the uploaded file in the console.
But I dont see it in the view.
Thank you
this is the whole function:
$('body').on('change', '#upload-input', function () {
var halloText = 'file';
var files = $(this).get(0).files;
if (files.length > 0) {
// create a FormData object which will be sent as the data payload in the
// AJAX request
var formData = new FormData();
// loop through all the selected files and add them to the formData object
for (var i = 0; i < files.length; i++) {
var file = files[i];
var message = buildMessage(myUserId, new Date().toISOString(), '<div class="imagepreview"><canvas id="progress' + imagecounter + '" width="80" height="80"></canvas><img id="image' + imagecounter + '"/></div>', 'sent');
message.classList.add('imagesender');
message.classList.add('imagesender' + imagecounter);
conversation.appendChild(message);
//processImages();
conversation.scrollTop = conversation.scrollHeight;
var myCanvas = document.getElementById('progress' + imagecounter);
var circle = new ProgressCircle({
canvas: myCanvas,
});
var percentComplete = 0.65;
circle.addEntry({
minRadius: 30,
fillColor: 'rgba(0, 0, 0, 0.5)',
progressListener: function () {
return percentComplete; // between 0 and 1
}
});
circle.start(33);
var extn = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
if (extn == "gif" || extn == "png" || extn == "jpg" || extn == "jpeg") {
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.id = imagecounter;
reader.onload = function (e) {
var imageid = imagecounter;
document.getElementById("image" + e.currentTarget.id).src = e.target.result;
};
reader.readAsDataURL(file);
} else {
// No filereader support... so no preview
}
}
imagecounter++;
// add the files to formData object for the data payload
formData.append('uploads[]', file, file.name);
}
formData.append('Token', SessionInfo.ImageToken);
formData.append('RoomId', currentRoom.RoomId);
dbgMessage(formData);
$.ajax({
url: apipath + '/devices/UploadData',
type: 'POST',
data: formData,
processData: false,
contentType: false,
done: function (data) {
},
error: function(jqXHR, textStatus, errorThrown ){
//show error as a message
var message = buildMessage(myUserId, new Date().toISOString(), jqXHR.responseText, 'error');
conversation.appendChild(message);
conversation.scrollTop = conversation.scrollHeight;
},
xhr: function () {
// create an XMLHttpRequest
var xhr = new XMLHttpRequest();
// listen to the 'progress' event
xhr.upload.addEventListener('progress', function (evt) {
if (evt.lengthComputable) {
// calculate the percentage of upload completed
percentComplete = evt.loaded / evt.total;
if (percentComplete == 1) {
var messagetext = '';
messagetext += '<span class="metadata">' + '<span class="filename">' + file.name + '</span>';
// Handle complete
$('.imagesender').hide();
dbgMessage('Upload complete ');
console.log(file.name);
}
}
}, false);
return xhr;
}
});
}
});
So that the file name will be visible in the html view.
if I do this:
$('.messagewrapper').append('<span class="metadata">' + '<span class="filename">' + file.name + '</span>');
Then it works only after I upload file.
But When I refresh the page the image file is not visible anymore
Like this:
if (percentComplete == 1) {
// Handle complete
$('.imagesender').hide();
dbgMessage('Upload complete ');
}
$('.messagewrapper').append("<p>"+ file.name+"</p>")
append based on id like this should work:
$('#messagewrapper').append("<p>"+ file.name+"</p>")
You will append this only when the file is uploaded because it is inside the if statement:
percentComplete = evt.loaded / evt.total;
if (percentComplete == 1){ //==1 means uploaded
//your append is here
So move it outside the if statement.
I manage to generate the thumbnail via the script below
$('input#fileupload').on('change', function() {
for (var i = 0; i < this.files.length; i++) {
var fr = new FileReader();
var name = this.files.item(i).name;
fr.onload = function(e) {
$('#thumbs ul').append('<li><img src="' + e.target.result + '"><span>' + name[i] + '</span></li>');
};
fr.readAsDataURL(this.files[i]);
}
});
But unable to insert the file name into the appended <li></li> element
The issue is because you're using files.item(i).name which is invalid. You instead need to access the files array by index, then get the name property.
Also note that when you append the variable in to the span, you can use name directly, not name[i].
Finally, you'll need to use a closure to maintain the scope of the current file when in the onload event handler. Try this:
$('input#fileupload').on('change', function() {
for (var i = 0; i < this.files.length; i++) {
(function(file) {
var name = file.name;
var fr = new FileReader();
fr.onload = function(e) {
$('#thumbs ul').append('<li><img src="' + e.target.result + '"><span>' + name + '</span></li>');
};
fr.readAsDataURL(file);
})(this.files[i])
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="fileupload" multiple="true" />
<div id="thumbs">
<ul></ul>
</div>
I'm trying to add preview and delete option before uploading multiple images, this is what I found:
$(document).ready(function() {
if (window.File && window.FileList && window.FileReader) {
$("#files").on("change", function(e) {
var files = e.target.files,
filesLength = files.length;
for (var i = 0; i < filesLength; i++) {
var f = files[i]
var fileReader = new FileReader();
fileReader.onload = (function(e) {
var file = e.target;
$("<span class=\"pip\">" +
"<img class=\"imageThumb\" src=\"" + e.target.result + "\" title=\"" + file.name + "\"/>" +
"<br/><span class=\"remove\">Remove image</span>" +
"</span>").insertAfter("#files");
$(".remove").click(function(){
$(this).parent(".pip").remove();
});
});
fileReader.readAsDataURL(f);
}
});
} else {
alert("Your browser doesn't support to File API")
}
});
But while uploading all images are getting uploaded, how to resolve this? I'm using php.
Ok, i'm create example that solved your problem:
Your HTML
<form method="post" id="sendForm">
<input type="file" id="files" multiple>
<input type="submit">
</form>
Your JS
$(document).ready(function() {
if (window.File && window.FileList && window.FileReader) {
// Array which stores all selected images
var sendData = [];
$("#files").on("change", function(e) {
var files = e.target.files,
filesLength = files.length;
for (var i = 0; i < filesLength; i++) {
var f = files[i]
var fileReader = new FileReader();
fileReader.onload = (function(e) {
var file = e.target;
$("<span class=\"pip\">" +
"<img class=\"imageThumb\" src=\"" + e.target.result + "\" title=\"" + file.name + "\"/>" +
"<br/><span class=\"remove\">Remove image</span>" +
"</span>").insertAfter("#files");
// Add all images to array
sendData.push({file: file, url: e.target.result});
$(".remove").click(function() {
var self = $(this).parent().children();
sendData.map(function(value, currentIndex, data) {
// Remove only image which removed from preview
if (self[0].currentSrc === value.url) {
sendData.splice(currentIndex, 1);
}
});
$(this).parent().remove();
});
$("#sendForm").submit(function(e) {
// Finally post all data to your PHP url that
$.post("your/php/url", sendData);
});
});
fileReader.readAsDataURL(f);
}
});
} else {
alert("Your browser doesn't support to File API")
}
});
i am a newbie with jquery and i was playing with this plugin. i am using it with asp.net and I want to get number of file dropped in it. I tried a bit but failed to get. Any idea?
Here is the code of script.js:
$(function () {
var dropbox = $('#dropbox'),
message = $('.message', dropbox);
dropbox.filedrop({
paramname: 'pic',
maxfiles: 100,
maxfilesize: 100,
//url: '/Uploader.asmx/Upload',
url: '/Default.aspx',
uploadFinished: function (i, file, response) {
$.data(file).addClass('done');
var count = file.size;
alert(count);
},
error: function (err, file) {
switch (err) {
case 'BrowserNotSupported':
showMessage('Your browser does not support HTML5 file uploads!');
break;
case 'TooManyFiles':
alert('Too many files! Please select 5 at most! (configurable)');
break;
case 'FileTooLarge':
alert(file.name + ' is too large! Please upload files up to 2mb (configurable).');
break;
default:
break;
}
},
//Called before each upload is started
// beforeEach: function (file) {
//if (!file.type.match(/^image\//)) {
//alert('Only images are allowed!');
// alert(file.name);
// Returning false will cause the
// file to be rejected
// return true;
// }
//},
uploadStarted: function (i, file, len) {
createImage(file);
},
progressUpdated: function (i, file, progress) {
$.data(file).find('.progress').width(progress);
}
});
var template = '<div class="preview">' +
'<span class="imageHolder">' +
'<img style="" />' +
'<p class="background: rgba(0, 0, 0, 0.75);"></p>' +
'<span class="uploaded"></span>' + // background: rgba(0, 0, 0, 0.75);
'</span>' +
'<div class="progressHolder">' +
'<div class="progress"></div>' +
'</div>' +
'</div>';
function createImage(file) {
var preview = $(template),
image = $('img', preview),
paragraph = $('p', preview);
var reader = new FileReader();
image.width = 100;
image.height = 100;
reader.onload = function (e) {
// e.target.result holds the DataURL which
// can be used as a source of the image:
//alert(e.target.result);
// $('p#filename').removeAttr('id');
// $('p').attr('id', 'filename' + num + '');
// $('p#filename').text(file.name);
paragraph.attr('id', 'filename').text(file.name);
image.attr('src', '../assets/img/fileicon.png');
num = num + 1;
};
// Reading the file as a DataURL. When finished,
// this will trigger the onload function above:
reader.readAsDataURL(file);
message.hide();
preview.appendTo(dropbox);
// Associating a preview container
// with the file, using jQuery's $.data():
$.data(file, preview);
}
function showMessage(msg) {
message.html(msg);
}
});
It's in the input element. I had a fiddle that uses it in a change event, in which case it's in event.target.files.
edit: should include the fiddle: http://jsfiddle.net/jorgthuijls/uh95y/3/ try it by attaching PDF's.
The relevant code here. This loops over the files and creates "preview" boxes for PDF's but you can just count it as well. files below is an array.
var filesInput = document.getElementById("files");
filesInput.addEventListener("change", function (event) {
var files = event.target.files; //FileList object
var output = document.getElementById("result");
for (var i = 0; i < files.length; i++) {
var file = files[i];
var reader = new FileReader();
reader.addEventListener("load", function (event) {
//stick some rubbish here to check the type of
//file loaded and adjust "type" below. See the
// 'reader' object, it has all that.
var div = document.createElement("div");
div.innerHTML
= '<object data="'
+ reader.result
+ '" type="application/pdf">'
+ '<embed src="'
+ reader.result
+ '" type="application/pdf" />'
+ '</object>';
output.insertBefore(div, null);
});
//Read the image
reader.readAsDataURL(file);
}
});