The simplest and most robust way I have done this in the past, is to simply target a hidden iFrame tag with your form - then it will submit within the iframe without reloading the page.
That is if you don't want to use a plugin, JavaScript or any other forms of "magic" other than HTML. Of course you can combine this with JavaScript or what have you...
<form target="iframe" action="" method="post" enctype="multipart/form-data">
<input name="file" type="file" />
<input type="button" value="Upload" />
</form>
<iframe name="iframe" id="iframe" style="display:none" ></iframe>
You can also read the contents of the iframe onLoad
for server errors or success responses and then output that to user.
Chrome, iFrames, and onLoad
-note- you only need to keep reading if you are interested in how to setup a UI blocker when doing uploading/downloading
Currently Chrome doesn't trigger the onLoad event for the iframe when it's used to transfer files. Firefox, IE, and Edge all fire the onload event for file transfers.
The only solution that I found works for Chrome was to use a cookie.
To do that basically when the upload/download is started:
- [Client Side] Start an interval to look for the existence of a cookie
- [Server Side] Do whatever you need to with the file data
- [Server Side] Set cookie for client side interval
- [Client Side] Interval sees the cookie and uses it like the onLoad event. For example you can start a UI blocker and then onLoad ( or when cookie is made ) you remove the UI blocker.
Using a cookie for this is ugly but it works.
I made a jQuery plugin to handle this issue for Chrome when downloading, you can find here
https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js
The same basic principal applies to uploading, as well.
To use the downloader ( include the JS, obviously )
$('body').iDownloader({
"onComplete" : function(){
$('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
}
});
$('somebuttion').click( function(){
$('#uiBlocker').css('display', 'block'); //block the UI
$('body').iDownloader('download', 'htttp://example.com/location/of/download');
});
And on the server side, just before transferring the file data, create the cookie
setcookie('iDownloader', true, time() + 30, "/");
The plugin will see the cookie, and then trigger the onComplete
callback.