In a multipart form, I can preview a single uploading image using:
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
let image = new Image();
image.src = `${e.target.result}`;
image.className = "img-thumbnail"
let closeBtn = `<button type="button" class="close"></button>`;
let wrapper = $('<div class="image-wrapper" />');
$('#images-to-upload').append(wrapper);
$(wrapper).append(image);
$(wrapper).append(closeBtn);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#imgInput").change(function () {
readURL(this);
});
But I'd like to preview ALL uploading images, so I made this adjustment to the code above by adding a for loop:
function readURL(input) {
if (input.files && input.files[0]) {
let files = input.files;
for (var i = 0; i < input.files.length; i++) {
var reader = new FileReader();
reader.onload = function (e) {
let image = new Image();
image.src = `${e.target.result[i]}`;
image.className = "img-thumbnail"
let closeBtn = `<button type="button" class="close"></button>`;
let wrapper = $('<div class="image-wrapper" />');
$('#images-to-upload').append(wrapper);
$(wrapper).append(image);
$(wrapper).append(closeBtn);
}
};
reader.readAsDataURL(input.files[i]); // error here
}
}
But now I get this error:
143 Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'
How can I fix this?
It's because the reader.readAsDataURL(input.files[i]);
is outside the loop. But this is not how you do this. The FileReader
can process only one file at the time. This means you have to create an instance of the FileReader
for each image in the input.
I would suggest to split it into 2 functions for readability.
function previewImage(file) {
const reader = new FileReader();
reader.onload = function (e) {
let image = new Image();
image.src = e.target.result;
image.className = "img-thumbnail";
let closeBtn = `<button type="button" class="close"></button>`;
let wrapper = $('<div class="image-wrapper" />');
$("#images-to-upload").append(wrapper);
$(wrapper).append(image);
$(wrapper).append(closeBtn);
};
reader.readAsDataURL(file);
}
function readURL(input) {
if (input.files.length) {
Array.from(input.files).forEach((file) => previewImage(file));
}
}
I made some changes:
if (input.files.length) {
- the file input always have files FileList
object so no need to check if it exists, and you just check if it has a length, meaning at least one file is presentArray.from(input.files)
- transforms FileList
into a regular array fo you can use array functions, like forEach
The rest is pretty much the same. In image.src = e.target.result;
, there's no need to make it string as it is already a string. Also the result set on the FileReader
class cannot be array.