A while back I wrote a simple example of using JavaScript to add file previews for a multi-file upload HTML control. You can find that entry here: Adding a file display list to a multi-file upload HTML control. I followed it up with another example (Multi-File Uploads and Multiple Selects) that demonstrated adding support for multiple selections. This weekend a reader asked for a way to remove files from the list before uploading. Here is an example of that.
First - I had to figure out how users would remove files. I could have added a button to each image preview, or a link. Anything really. But to make things simpler, I decided that a click on the image would remove it. Obviously that may not be the best UX. I added a title attribute to help make this clear. You should be able to easily modify my code to change how this works. Let's look at the code and then I'll explain the changed bits. (If you didn't read the previous entries though, please do so. I won't be going over the basics again.)
<!doctype html>
<html>
<head>
<title>Proper Title</title>
<style>
#selectedFiles img {
max-width: 200px;
max-height: 200px;
float: left;
margin-bottom:10px;
}
</style>
</head>
<body>
<form id="myForm" method="post">
Files: <input type="file" id="files" name="files" multiple><br/>
<div id="selectedFiles"></div>
<input type="submit">
</form>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script>
var selDiv = "";
var storedFiles = [];
$(document).ready(function() {
$("#files").on("change", handleFileSelect);
selDiv = $("#selectedFiles");
$("#myForm").on("submit", handleForm);
$("body").on("click", ".selFile", removeFile);
});
function handleFileSelect(e) {
var files = e.target.files;
var filesArr = Array.prototype.slice.call(files);
filesArr.forEach(function(f) {
if(!f.type.match("image.*")) {
return;
}
storedFiles.push(f);
var reader = new FileReader();
reader.onload = function (e) {
var html = "<div><img src=\"" + e.target.result + "\" data-file='"+f.name+"' class='selFile' title='Click to remove'>" + f.name + "<br clear=\"left\"/></div>";
selDiv.append(html);
}
reader.readAsDataURL(f);
});
}
function handleForm(e) {
e.preventDefault();
var data = new FormData();
for(var i=0, len=storedFiles.length; i<len; i++) {
data.append('files', storedFiles[i]);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.cfm', true);
xhr.onload = function(e) {
if(this.status == 200) {
console.log(e.currentTarget.responseText);
alert(e.currentTarget.responseText + ' items uploaded.');
}
}
xhr.send(data);
}
function removeFile(e) {
var file = $(this).data("file");
for(var i=0;i<storedFiles.length;i++) {
if(storedFiles[i].name === file) {
storedFiles.splice(i,1);
break;
}
}
$(this).parent().remove();
}
</script>
</body>
</html>
The first big difference in this version is the use of jQuery. I didn't really need it before so I used querySelector instead. I needed to make use of jQuery's simple handling of post-DOM manipulation event binding (let me know if that doesn't make sense) so I added in the library. I've added my click handler here:
$("body").on("click", ".selFile", removeFile);
I then modified the image display to include the class and title attribute.
var html = "<div><img src=\"" + e.target.result + "\" data-file='"+f.name+"' class='selFile' title='Click to remove'>" + f.name + "<br clear=\"left\"/></div>";
Notice I added a div around the image and file name. This will make sense in a second. Now let's look at the handler.
function removeFile(e) {
var file = $(this).data("file");
for(var i=0;i<storedFiles.length;i++) {
if(storedFiles[i].name === file) {
storedFiles.splice(i,1);
break;
}
}
$(this).parent().remove();
}
Not really rocket science. I find the file in the existing list, remove it, and then remove the image/file text from the DOM. Done.
Archived Comments
I have played around several times with file uploads but have never taken the jQuery method for uploading files. I have seemed to have success with just CF. I may have to create a demo with this example you created and do some testing with it for possible future coding options. Cool, hope you had a good weekend.
Slightly off topic, but I had a good play with Adobe FormsCentral last night and quite frankly I am blown back. Also got me thinking, who needs sever validation if you need JavaScript to see the form.
You *always* need server-side validation. Period. You need not have "friendly* server-side validation, i.e. you may just output ERROR, but you *must* check your input on the server. Period.
Let's take your example of a form that isn't even visible unless you have JS. I'd simply run the page, look at where it POSTS, and I'd try to attack your server that way.
D'oh! Didn't even think about that. Suppose the same if it's just a JavaScript link to the form too.
Détails de l’erreur de la page Web
Agent utilisateur : Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; BTRS98585; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Horodateur : Fri, 16 May 2014 18:43:15 UTC
Bonjour,
Félicitation pour ce programme..
Je l'ai essayer pour me faire un site ou je gère une gallerie de peintures
ce programme de download est super par contre il fonctionne sous Firefox mais sous IE8 j'ai l'erreur ci-dessous :
Message : Objet attendu
Ligne : 32
Caractère : 3
Code : 0
y à t'il une solution pour que ça marche ?
As I don't speak French (and I'm not sure why you would think I do as I've never used it on the blog), I can't help you.
Karim, try moving the document ready code to the end of that script block so the two function definitions are before it.
Hmm, actually, thinking about that the functions should be hoisted above the document ready stuff... right Ray?
I counted line 32 to be the document ready and just assumed the missing object error was due to that but I haven't actually tested this on IE8 (which I have on a VM)... so I should probably do that before offering any assistance :)
Hello I'm happy that you are to give me a rapid reponce.
i don't speak English ...
excuse me if i do some error when i script.
a'm added some lines in your code and now there is not error in the new script.
But there is away no image on the screen.
The Code I'm added provide to different sites and examples for to compensate the compatibility on IE8.
I'm going to see the address of SCR perhaps I'm while find Where is my error.
Merci pour votre aide.
Cordialement.
<!doctype html>
<html>
<head>
<title>Proper Title</title>
<style>
/* #selectedFiles img {
max-width: 200px;
max-height: 200px;
float: left;
margin-bottom:10px;
}*/
#selectedFiles img {
width: 160px;
height: 120px;
border:1px solid;
float:right;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);
}
</style>
</head>
<body>
<div id="selectedFiles"></div>
<form id="myForm" method="post">
Files: <input type="file" id="files" name="files" multiple><br/>
<input type="submit">
</form>
<!--<script type="text/javascript" src="http://ajax.googleapis.com/..."></script>-->
<script type="text/javascript" src="jquery-git1.js"></script>
<script language="javascript">
var selDiv = "";
var storedFiles = [];
//$(document).ready(function() {
jQuery(document).ready(function(){
$("#files").on("change", handleFileSelect);
selDiv = $("#selectedFiles");
$("#myForm").on("submit", handleForm);
$("body").on("click", ".selFile", removeFile);
});
/**
* Shim for "fixing" IE's lack of support (IE < 9) for applying slice
* on host objects like NamedNodeMap, NodeList, and HTMLCollection
* (technically, since host objects have been implementation-dependent,
* at least before ES6, IE hasn't needed to work this way).
* Also works on strings, fixes IE < 9 to allow an explicit undefined
* for the 2nd argument (as in Firefox), and prevents errors when
* called on other DOM objects.
*/
(function () {
'use strict';
var _slice = Array.prototype.slice;
try {
// Can't be used with DOM elements in IE < 9
_slice.call(document.documentElement);
}
catch (e) { // Fails in IE < 9
Array.prototype.slice = function (begin, end) {
var i, arrl = this.length, a = [];
// Although IE < 9 does not fail when applying Array.prototype.slice
// to strings, here we do have to duck-type to avoid failing
// with IE < 9's lack of support for string indexes
if (this.charAt) {
for (i = 0; i < arrl; i++) {
a.push(this.charAt(i));
}
}
// This will work for genuine arrays, array-like objects,
// NamedNodeMap (attributes, entities, notations),
// NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
// and will not fail on other DOM objects (as do DOM elements in IE < 9)
else {
// IE < 9 (at least IE < 9 mode in IE 10) does not work with
// node.attributes (NamedNodeMap) without a dynamically checked length here
for (i = 0; i < this.length; i++) {
a.push(this[i]);
}
}
// IE < 9 gives errors here if end is allowed as undefined
// (as opposed to just missing) so we default ourselves
return _slice.call(a, begin, end || a.length);
};
}
}());
'use strict';
// Add ECMA262-5 method binding if not supported natively
//
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
if (arguments.length<=1) {
return function() {
return that.apply(owner, arguments);
};
} else {
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
};
}
};
}
// Add ECMA262-5 string trim if not supported natively
//
if (!('trim' in String.prototype)) {
String.prototype.trim= function() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
};
}
// Add ECMA262-5 Array methods if not supported natively
//
if (!('indexOf' in Array.prototype)) {
Array.prototype.indexOf= function(find, i /*opt*/) {
if (i===undefined) i= 0;
if (i<0) i+= this.length;
if (i<0) i= 0;
for (var n= this.length; i<n; i++)
if (i in this && this[i]===find)
return i;
return -1;
};
}
if (!('lastIndexOf' in Array.prototype)) {
Array.prototype.lastIndexOf= function(find, i /*opt*/) {
if (i===undefined) i= this.length-1;
if (i<0) i+= this.length;
if (i>this.length-1) i= this.length-1;
for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
if (i in this && this[i]===find)
return i;
return -1;
};
}
if (!('forEach' in Array.prototype)) {
Array.prototype.forEach= function(action, that /*opt*/) {
for (var i= 0, n= this.length; i<n; i++)
if (i in this)
action.call(that, this[i], i, this);
};
}
if (!('map' in Array.prototype)) {
Array.prototype.map= function(mapper, that /*opt*/) {
var other= new Array(this.length);
for (var i= 0, n= this.length; i<n; i++)
if (i in this)
other[i]= mapper.call(that, this[i], i, this);
return other;
};
}
if (!('filter' in Array.prototype)) {
Array.prototype.filter= function(filter, that /*opt*/) {
var other= [], v;
for (var i=0, n= this.length; i<n; i++)
if (i in this && filter.call(that, v= this[i], i, this))
other.push(v);
return other;
};
}
if (!('every' in Array.prototype)) {
Array.prototype.every= function(tester, that /*opt*/) {
for (var i= 0, n= this.length; i<n; i++)
if (i in this && !tester.call(that, this[i], i, this))
return false;
return true;
};
}
if (!('some' in Array.prototype)) {
Array.prototype.some= function(tester, that /*opt*/) {
for (var i= 0, n= this.length; i<n; i++)
if (i in this && tester.call(that, this[i], i, this))
return true;
return false;
};
}
function handleFileSelect(e) {
var files = e.target.files;
var filesArr = Array.prototype.slice.call(files);
filesArr.forEach(function(f) {
if(!f.type.match("image.*")) {
return;
}
storedFiles.push(f);
var reader = new FileReader();
reader.onload = function (e) {
var html = "<div><img src=\"" + e.target.result + "\" data-file='"+f.name+"' class='selFile' title='Click to remove'>" + f.name + "<br clear=\"left\"/></div>";
selDiv.append(html);
}
reader.readAsDataURL(f);
});
}
function handleForm(e) {
e.preventDefault();
var data = new FormData();
for(var i=0, len=storedFiles.length; i<len; i++) {
data.append('files', storedFiles[i]);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.cfm', true);
xhr.onload = function(e) {
if(this.status == 200) {
console.log(e.currentTarget.responseText);
alert(e.currentTarget.responseText + ' items uploaded.');
}
}
xhr.send(data);
}
function removeFile(e) {
var file = $(this).data("file");
for(var i=0;i<storedFiles.length;i++) {
if(storedFiles[i].name === file) {
storedFiles.splice(i,1);
break;
}
}
$(this).parent().remove();
}
</script>
</body>
</html>
If you can, please do not post large blocks of code here. My auto formatting tends to break some of it. In the future, use a Gist or Pastebin instead. Is this online where I can see it and run it?
OK ,
I' continuous to work on this code.. and I'm give you regularity my results about it ..
Hello, Raymond. Thank you for the code. I have tried to put them into my page. But I found that even the file has been removed from the list displaying in the page, the file still uploaded (or say Post) to the server. Is the reason (removed file) still contain in the input tag?
I now know that the handleForm is triggered by <input type="submit"> , right ? But my form is using a button to first go to a javascript to valid the form before submission. *document.getElementById("myform").submit();* I will use it to subit the form. So how can i change the method to prevent uploading the file which is removed ?
Without seeing your code I really can't comment. You would need to completely stop the form submit and chain off to my code after validation. If you are using other form fields then they would need to be appended too.
Hi, i am testing your code, but it is uploading only one file from more.
Any help?
Put it online where I can test and I'll try and see if something stands out in the console.
files not removed.
var file = $(this).data("file");
alert(file);
alert shows undefined....why?
@vinay: I don't understand your comment. Can you add more?
Am trying your code in MVC 4
But , function removeFile(e) {.... this function is deleting from temp array - storedFiles,
But while posting all the selected files are posted , Deletion NOT Working :(
Pls check this :
http://pastebin.com/ZFZux1ck
I just tested my code again in Chrome and it worked correctly. Your code does not match mine, so I'd recommend updating it.
Hi,
i tried , Am using asp MVC :
from my code : xhr.send(data);
is not getting fired to my controller action.
What could be possible reason ?
Open up the developer console on your browser and see if an error is being reported. You can also see if the submit handler is firing correctly.
Hi Raymond,
Your code is working fine.Error was at my end.
Thanks for the same
I have one more issue.
I need to post the form data also.I am using mvc4.
If i comment the e.preventdefault() the form data gets posted, but the attachments that i deleted is not removed.
How can this be done.(Post the form data as well as upload the attachments with the remove functionality intact)
Please refer the code snippet
http://pastebin.com/Pi7NTyMP
Regards,
Rigin
"If i comment the e.preventdefault() the form data gets posted, but the attachments that i deleted is not removed."
Ok, so then the remove action is not working for you. Think about it then - how would you debug this? I'd add console.log messages to the remove action to ensure that the delete is working properly. You can check the length of the array for example to ensure it is one less.
After removing one action, the posted all files are getting uploaded ... removed one also.
Then how can we get the updated list of attachments in action ? can you brief please
I do not know what you mean - "by removing one action".
See what I meant is : am getting all the files that we selected in the input file element in my action method .
But the model am that received in action is empty one.
How can I get the model from form where am firing this submit ? I also need the other form data..textbox, dropdown and all...
are you clear with my query ? please let me know
"But the model am that received in action is empty one."
I do not understand what you mean here. If you use your Dev Tools and see all the files being posted (which you *can* do with Chrome's Network tools), then the issue is with your server-side code and I can't help you with that.
"How can I get the model from form where am firing this submit ? I also need the other form data..textbox, dropdown and all..."
In my example, I create a form post consisting of JUST the files. You can add additional file fields too. See the docs for FormData: https://developer.mozilla.o...
thanks for your help :)
Hi, thanks a lot for you help.
I'm developing a CMS where the user can select multiple files to upload, but the problem that I faced is I can't remove a certain file from the multiple files.
I know that the input file is readonly so we don't have any control on it :(
You did that, but I don't want to use ajax, So Is there a way to remove a certain file from the selected files ?
Not that I know of. I'm not saying it is impossible, but I don't think you can. You could consider a Flash based widget.
I don't understand you Raymond
Not sure how else I can say it. There are upload controls built with Adobe Flash. If you Google, you can find a bunch.
i used your code all thing about select multiple image and uploading is good but there is an issue, for Example: when i select 5 image the preview of five image are appear. and when i delete 2 image to click on image and save the form then in database all five images are stored. that is a wrong thaing.
So can you provide the solution for that on my email id which i used in that post.
Thanks
It should work and if it does not, please show me where it is online and I will try to test there.
hi my friends, nice plugin, but when I delete picture stay in value it. how edit this problem. thank you again
Please see my last reply. If you can share the URL, I'll take a look. Also, what browser did you test with?
what I mean, your code if I delete picture by clicking, I want to delete it from choseen file of browser, at the same time.
EXAMPLE;
First;
Choseen File 5 Files
after deleting picture;
Choseen File 5 Files
I want;
Choseen File 4 Files
If I delete a few
The FIle Picker control is only for the CURRENT selection. Once you dismiss it and return, it will not show you previously selected items.
S'il vous plaît, j'ai un problème dans <form id="myForm" method="post" action="test.html">
Files: <input type="file" id="files" name="files" multiple><br/>
<div id="selectedFiles"></div>
<input type="submit">
</form>
n ' envoyer pas les image
Please, I have a problem in <form id = "myForm" method = "post" action = "test.html">
Files: <input type = "file" id = "files" name = "files" multiple> <br/>
<div id = "selectedFiles"> </ div>
<input type = "submit">
</ form>
do not send the picture
Do you see an error in the console?
XMLHttpRequest cannot load file:///C:/Users/Imen/Desktop/photo/handler.cfm. Cross origin requests are only supported for protocol schemes: http, data, chrome-extension, https, chrome-extension-resource. test3.html:1
Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'file:///C:/Users/Imen/Desktop/photo/handler.cfm'. test3.html:80
Are you testing with a local web server or just by opening the file? You should test with a web server.
I testing with a local web server
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost/imen/projet/handler.cfm
So the next question is, does handler.cfm exist?
yes
You should double check then. The error says it does not exist. If you open your browser to that URL, what do you get?
Hi Raymond, thank you for this very useful information. I have managed to get the handleForm's output data into a controller where I manipulate the images.The problem is I can't then send the images to a view with "View::make ->with " . No error messages but Laravel refuses to do it. Do I need to use return Response::json([]) and can you advise me how I could do this.
I'm sorry, but I don't even know what Laravel is.
Sorry, it was presumptuous of me to assume that you would. Looking at your code in handleForm I can take the FormData object and have lots of fun with the images in a PHP code block but when I try to export the images to another page the fun stops. The same setup without jQuery works fine so I am assuming jQuery needs something returned (like with Response::json()). Just wondered if you could give me an idea how to implement that with your code in handleForm. Thanks.
Um... so to be clear. My code works to *post* to your server, but you don't know how to respond back to it to let it know that... it did something? Not quite sure I get what you mean. Also, I don't really know PHP. If your server side code needs to return a message to the client side code, you should probably reply with a JSON encoded msg. How that is done in PHP is not something I can help with.
Hi, how can i read storedFiles array with files in PHP? Thanks a lot
You can't - it is a client-side variable. You can use XHR to send JS data to the server of course.
I tried to apply this technique in my module but after remove the selected file and submit the form then all of files are uploaded including removed files. i think my form is not update after remove file. how can i fix it?
Is it online where I can test it? Do you see an error in the console?
Sorry for my late. no its on my local server. if you want i can send you by mail.
Typically code review of this sort is a paid engagement only. If you put it online though I don't mind giving it a quick look. I'd suggest looking in the console to see if you see an error.
How can i get files content after delete from #files
Not sure what you mean in this comment. To the first comment, I'd look for an error in the console.
before append data, there is any way to know how many files in my input field
Yes - it is an array and you can check the length.
how?
Given X is an array, in JS you can just do X.length.
Hi, I tried with your code and it works for deleting image per click but on submit, that removed images appear on the page (as they were added to the database and loaded for display). Any workaround?
What database?
I'm using it on a Mantis system, PHP webApp with MySQL database. Here is the screen cast about that.
https://youtu.be/UFgwnRvIApE
Interesting. Chrome definitely held on to the files. I'll have to think about this and get back to you.
So yep - you found a pretty major bug with my implementation. I don't remove the File object from the FileList value on the input field. In CHrome and Firefox, this is read only. There is a solution though - you switch to using XHR2 to upload. I'll put this in my queue to update.
I figure if I add this line <script>function toArray(o) { return [].slice.call(o) }</script> before calling ajax.googleapis jquery.min.js and your code. I can have right images stored and displayed for bug review (MantisBT is bug tracking webApp).
But I couldn't do away with photos remained on screen even after selecting another batch of photos. (1:39 -1:41 in my linked youtube video). In other word, I would like to clean up all preview photos whenever user starts over by clicking Choose files... and show them new preview photos as they have selected a new batch. How to do so, sir?
Thanks
So - the issue you'll have even with using XHR2 to post is that the UI will still say "N files". So I'm digging more.
Here is the fix:
// slide the array call.
+ <script>function toArray(o) { return [].slice.call(o) }</script>
<script type="text/javascript" src="http://ajax.googleapis.com/..."></script>
function handleFileSelect(e) {
+ selDiv.empty();
var files = e.target.files;
...}
// in handleFileSelect, you empty the element selDiv, so it starts fresh every time user clicks Choose Files/Images to upload...
Cheers,
Get back to me if it resolves your major bug?
This isn't going to work - the list of files associated w/ the input field is read only. You can't slice it.
Okay, once you figure it out, please keep me posted.
Ok, so update. I actually forgot I was using XHR2 to push. The issue is *just* the label on the file input field. If you do this:
e.target.value='';
in handleFileSelect, it makes the label around the field switch to No files selected. That *could* be confusing - but it is better than it showing X files when you had picked X and then removed one.
To be clear, my code *as is* only has the confusing label. I can confirm that when you submit, it works perfectly well.
hi sir, i'm using your code for my project. i think the problem are same as the other on the comment below..
1st i pick 3 picture
then i delete 1 picture
and lastly i submit the picture
and the result all the picture including the 1 that i delete before submit uploaded.
what i want to know is, is there any way that i can do so just the remaining picture uploaded and which i delete removed.
i attach the picture bellow. the code all the same as you posted up there nothing changed just adding submit function.
thanks for your time. this code is so cool if it can work properly.
Is it online where I can see?
not online yet sir..
so i make it like this..
function removeFile(e) {
selInput.empty();
var inpuTan = '';
var file = $(this).data("file");
for(var i=0;i<storedfiles.length;i++) {="" if(storedfiles[i].name="==" file)="" {="" storedfiles.splice(i,1);="" break;="" }="" }="" $.each(storedfiles,function(key,val){="" inputan="" +="val.name+',';" });="" selinput.val(inputan);="" $(this).parent().remove();="" }="" then="" at="" the="" controller="" before="" i="" save,="" i="" will="" loop="" it="" to="" check="" which="" removed="" which="" not="" then="" save="" the="" data="" tha="" i="" need="" to="" the="" database..="" :d="" i="" just="" dont="" know="" how="" to="" delete="" the="" stored="" files..="">
http://pastebin.com/29pX9SEE
Nothing sticks out. If you can get it online so I can run it, let me know. Also look for errors in the console.
its all cool code mate. I implement this, and all works at one time. Thanks Sir for this code. Its been 1-2 weeks I have been searching this feature in a simple way(deleting preview as well as its value).
Glad it worked for you. If you can bill a client, hit up my Amazon Wish List. ;)
Hi Raymond, i found your code very useful thanks for worth sharing. Please help on how to send an image on a file system and storing the image path on mysql database?
Your help will be appreciated.
My code should work as is for images. As for storing the image path, your form processor would handle that.
Thanks Sir for your quick response, real appreciate for this. I am new in php and jquery and struggling to learn. For the first part of storing on the file system works fine but can you write a code for the second part i.e storing image path in mysql database.
From this code:
form id="myForm" method="post">
Files: <input type="file" id="files" name="files" multiple="">
<div id="selectedFiles"></div>
<input type="submit">
</form>
how can i post the file path to the database since the form handles multiple form attributes?
Please Help
Expecting much from you.
I don't know PHP, so I can't help you with that.
Thanks Sir.Any other possible solution for this?
Please Help
Sure - PHP can process forms and file uploads just fine. I don't know how to code PHP, but I know it supports this. Please see the PHP docs.
Thanks Sir, let me check
You Nailed! fantastic, I was going nuts looking around, found many crazy ways of doing this, this was the more straight and simple way. I used this to simplify even more my code. Thank you sir!
You are most welcome.
I can help you out, I used Mr. Camden code on a php project, and I use jquery $.ajax instead of httpRequest, posting to a php page.
how to multiple images shows in web page
Sorry - what?
Hai, this is a great article, I have a small doubt, `data.append('files', storedFiles[i]); ` in this line, what does the `files` refer to? is it ID or the name?
I am getting an issue in removing the files.
It refers to the name of the form 'key' - such that when you post, you would look for a form field called files.
Change Your code as
data.append('files['+i+']', storedFiles[i]);
for Multiple Upload
No - that's only if your app server requires it. ColdFusion, for ex, does not.
oh,you really help me so much ! you are my hero!! Thank you so so so much!
The code works fantastically.. Absolutely what I was looking for.. Thanks..
hi
Raymond sir,
i want to ask you when we upload multiple fiile and preview image this is helpful for me .. thanku for this
But whenever we upload 5 seleted file then preview it and now one more image add in a queue then we insert in single image. which image is last image to insert .. thn how to save all file . Please tell us
I have no idea what you are saying here. Can you rephrase?
Hello Sir,
Nice plugin for muliple image uploding. I wanna to ask what i will have to do if i want to send some additional data with image uploading like if each image has a image category .
You can just send form fields along. You would need to associate file X with form field meta value Y but it is definitely doable.
https://uploads.disquscdn.c...
Thanks for quick reply. I am not getting exactly what u wanna say. I have atteched a snapshot what i want exactly. catagory select box bind with each image. Please give me some hint or example code.
I kinda gave you a hint already. When doing a POST with XHR, you can send form fields along that contain any data you want. Give you want to associate a dropdown with each file, you could use form fields named like so:
category1
category2
where 1 matches the first image, and so on.
Hello Sir,
Its only show the images how I can show and remove other mime types like pdf, doc and rar etc?
You would need to find someway of representing them. For example, find an image that represents PDF, like maybe the logo, and use that image instead.
I'm trying to use your code to upload multiple images through PouchDB. For this to work I need to have a variable set to equal the array of images - then that variable gets submitted through PouchDB. I've got an example on jsbin that I had tried to add your code into and couldn't get that working. The link here contains the working code that allows me to submit one image, but not multiple images: http://jsbin.com/haturuk/ed...
Your code in a working jsbin: http://jsbin.com/posecek/2/...
Any chance you can provide any pointers?
Thanks!
Since the array of images is stored in storedFiles, you can get the length just by doing storedFiles.length. Right?
Hmm. One of the keepers of PouchDB suggested this: https://gist.github.com/nol...
But no luck.
I'll toil on...
One more question. I can't figure out how to put the images to populate the screen going across the page instead of vertically. Any chance you can think of an easy modification so that they'll go across, wrapping to the next line when the fill the width of the the div? (<div id="selectedFiles" style="max-width: 900px">)
Like this:
img1 img2 img3
img4 img5
That's just CSS. I'd build a new HTML file with 5 hard coded images, work on your CSS, then apply it to that.
I had tried, and failed on that route. Now I got it:
var html = "<div class="myCustImg"><img src="\""" +="" e.target.result="" +="" "\"="" data-file=""+f.name+"" class="selFile" title="Click to remove">" + "</div>";
with the class defined as:
.myCustImg {
display: inline-block;
}
Thanks for the fantastic tool!!!
How did it fail?
I actually can't remember what I tried before this - but it was more complicated and didn't work. This was quite simple and works perfectly!
Oh cool. Well if you get rich doing this, visit my Amazon Wish List please. ;)
Rich won't be in the cards I don't think. But if I do ...
:)
Hey, thank you for this, I've implemented this code and it works fantastic for previewing mutliple image uploads with the ability to delete and upload more, but I'm having problem with the images being submitted. I've modifed to the code to send my other inputs and that part works, but the images themselves arent being sent. I have my php side respond with whats it getting, and its getting the inputs but not images. The problem seems to be that .append isnt assigning images to the array, because it does create and send the image when its changed to a string. Here is what the server is getting when its trying to load images, and when that bit is changed to a string:
https://gyazo.com/484c38d72...
https://gyazo.com/2a3c9e4e6...
https://gyazo.com/03bdc64a7...
https://gyazo.com/abf36bd21...
Its data.append('files', storedFiles[i]); that seems to be the problem, what I can do to make it work?
Is this online where I can test myself? Do you see any errors in the console?
I was putting it online to show you, but during that I accidentally got it to work. One of the mistakes was not using a $_FILES array in php. You also have to put [] at the end of 'files' to make it into array it seems.
Here is the end result of it working with the data structure as its received:
https://i.gyazo.com/eb8460c...
https://i.gyazo.com/29224ba...
For those wondering how to call it in php, it would be $_FILES['files']['name'][0] for example, to get the name of the first one. Seems a bit counterintuitive to have the number indexes after the associative ones, but what can you do.
Either way thanks again for this implementation, saved my life on a project.
Ah, glad you got it!
Would there be a way to use canvas.width and canvas.height to redraw the preview image instead of CSS? The reason as that some users want to print to PDF on a mobile device - this results in the full size image being used in the PDF and huge PDF's.
I was thinking that something like below could work but I can't figure out what to replace e.target.result with to get the resized images to show in preview (var html = "<div><img src="\""" +="" e.target.result="" +="" "\"="" data-file=""+f.name+"" class="selFile" title="Click to remove">" + "</div>";)
Thanks for all your help! https://uploads.disquscdn.c...
I really have no idea what you mean. Are you allowing the user to select PDFs, not images
Sorry if I wasn't clear. The form that uses your code is sometimes printed out after the details are entered. Usually when printed it is printed to PDF. When this is done the underlying image data for the image present in the browser view of this form is the user selected image at it's native size, not the resized size. This creates enormous PDF files pretty easily. I believe the workaround would be to use canvas to redraw the image at lower size/resolution for the web view - then when the web view is printed it will be this lower resolution file that is printed.
Any ideas on this?
Thanks!
Odd that the "Print to PDF" feature is ignoring the CSS. Maybe add a width="X" to the img tag where X matches the max width used in the CSS.
Unfortunately that doesn't work either - the PDF created from the web form on iOS still embeds the full size image.
Thanks for your help!
Maybe look into a client-side library to resize the image. That's an option.
This was great man but can you help me on how can i upload it to the sql database i am using asp.net c#. thanks in advance and also how can i limit into 4 maximun of they upload
I've never used ASP.Net so I can't help with this. As for the max, since you can read the length of the files array, you can check for that and when it is too high, prevent form submission.
Hi Raymond, I find this blog really helpful in my website although there's a bit of problem. whenever I remove the images, its still on the selected item not remove(only the image/s). Thanks, hoping for your help.
Add a console.log(storedFiles.length) before and after the splice - see if it's properly resizing.
I'm struggling to figure out where to put the console.log(storedFiles.length), can you provide any more guidance?
I've got a working demo here: http://jsbin.com/posecek/6/...
Thanks!
Err, before and after the splice -
storedFiles.splice(i,1) - that's in the remove handler.
I used your jsbin, added 3 files, removed one, and checked storedFiles.length in the console - it was 2.
Right, the console.log works. But the number of files shown next to the Browse box does not update. Is there a way to get that to update with the number of files?
The screenshot below would show the 3 images below the Browse button and above the 'Select an image' https://uploads.disquscdn.c... comment. As shown, I've selected the 3 images to remove them, but the image count shown is still 3.
As far as I know you can't change that, but you can maybe use CSS to hide the entire UI.
Added fontawesome to show extension based on the selected file and removing files with delete icon will work fine, please check the console when removing files.
https://jsfiddle.net/athish...
So - to be clear - you are sharing your version - not asking for help, right? :)
Yeah, just a little add-on of icons. Thanks for the fantastic code snippet, made my life easy :)
hai sir,
i want to display 5image using array.after displaying 5img i want to add image using some button
Sorry I honestly don't know what you are asking here.
Hey can you tell me how to do this in react js???
Hello Sir,
Really helpful article. Thank you.
hello Raymond Camden when removing images its only removes the preview not from in input file.. can you please help me to delete that file from input also.. thanks in advance :)
here i have select 9 images from computer and then remove some images...but its still show me 9.. please help me to resolve these problem
Please share an online version where I can test.
Great explanation. Read all previous 3 blogs. Sir i having trouble saving the images. I am using the form to send data to php page, where i upload the file into server, and then save file name in database. So i modified the code a little bit, and when i submit the form , the data being sent over to php page says after var_dump($_POST) as array(0){};
https://drive.google.com/op...