There is the code https://jsfiddle.net/bfzmm1hc/1 Everything looks fine but I want to delete some of the files from the set.
I have already found these:
- How to remove one specific selected file from input file control
- input type=file multiple, delete items
I know that FileList
object is readonly, so I can just copy the files to a new array. But what should I do with this new array of File
objects? I can't assign it to the files
property...
Since you cannot edit the Read Only input.files
attribute, you must upload a form using XMLHttpRequest
and send a FormData
object. I will also show you how to use URL.createObjectURL
to more easily get a URI from the File
object:
var SomeCl = {
count: 0,
init: function() {
$('#images').change(this.onInputChange);
},
onInputChange: function() {
// reset preview
$('.container').empty();
// reset count
SomeCl.count = 0;
// process files
SomeCl.processFiles(this.files, function(files) {
// filtered files
console.log(files);
// uncomment this line to upload the filtered files
SomeCl.upload('url', 'POST', $('#upload').get(0), files, 'images[]');
});
},
processFiles: function(files, callback) {
// your filter logic goes here, this is just example
// filtered files
var upload = [];
// limit to first 4 image files
Array.prototype.forEach.call(files, function(file) {
if (file.type.slice(0, 5) === 'image' && upload.length < 4) {
// add file to filter
upload.push(file);
// increment count
SomeCl.count++;
// show preview
SomeCl.preview(file);
}
});
callback(upload);
},
upload: function(method, url, form, files, filename) {
// create a FormData object from the form
var fd = new FormData(form);
// delete the files in the <form> from the FormData
fd.delete(filename);
// add the filtered files instead
fd.append(filename, files);
// demonstrate that the entire form has been attached
for (var key of fd.keys()) {
console.log(key, fd.getAll(key));
}
// use xhr request
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.addEventListener('progress', function(e) {
console.log('lengthComputable', e.lengthComputable);
console.log(e.loaded + '/' + e.total);
});
xhr.addEventListener('load', function(e) {
console.log('uploaded');
});
xhr.addEventListener('error', function(e) {
console.log('this is just a demo');
});
xhr.send(fd);
},
preview: function(file) {
// create a temporary URI from the File
var url = URL.createObjectURL(file);
// append a preview
$('.container').append($('<img/>').attr('src', url));
}
};
SomeCl.init();
.container img {
max-width: 250px;
max-height: 250px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="upload">
<input name="other" type="hidden" value="something else">
<input name="images[]" id="images" multiple="multiple" type="file">
<div class="container"></div>
</form>
I found a workaround. This will not require AJAX for the request at all and the form can be sent to the server. Basically you could create an hidden
or text
input and set it's value
attribute to the base64 string created after processing the file selected.
<input type=hidden value=${base64string} />
You will probably consider the idea to create multiple input file instead of input text
or hidden
. This will not work as we can't assign a value to it.
This method will include the input file in the data sent to the database and to ignore the input file you could:
- in the back-end don't consider the field;
- you can set the
disabled
attribute to the input file before serialising the form;
- remove the DOM element before sending data.
When you want to delete a file just get the index of the element and remove the input element (text or hidden) from the DOM.
Requirements:
- You need to write the logic to convert files in base64 and store all files inside an array whenever the input file trigger the
change
event.
Pros:
- This will basically give you a lot of control and you can filter, comparing files, check for file size, MIME type, and so on..