问题
Is there true asynchronous/ajax file uploading in grails that hooks into the default "busy" spinner (the one that shows on other ajax calls)?
Or if I wanted to show that spinner during a file upload would I need to call is explicitly?
回答1:
This is one of those things that you usually want some help from a third party because of some of the complexities and restrictions behind the exchange.
Some plugins are available for jquery that use Flash to accomplish this but I prefer to avoid anything that uses Flash (personal preference). Check out Valums Ajax-Upload I've used it now for about a year in my production site and it works well and was easy to use. My favorite thing about the plug-in is that it's unobtrusive to the design and layout of most any site.
Also, this is a commonly asked question. Check out these answers as well...
- Stackoverflow - Is it possible to use Ajax to do file upload?
- Stackoverflow - remote file upload
- Stackoverflow - Ajax file upload
回答2:
Jeff,
I would code like this...
- Take just the file path from the user.
- Send the file path to fileupload closure/method and in the asynchronous block do the file reading and save.
- You might need to use Executor plugin for this for asychronous functionality.
- In this scenario you don't need spinner image to display. Because submitting the file path is very simple and response is very fast.
You have to call the spinner if at all you want to display yourself in the code. If you want to display the image.
回答3:
You can use XMLHttpRequest, here is the complete code from a project that i done with drag and drop included:
HTML
<div id="drop_zone">Drag and drop your file here or click</div>
<input id="curriculumUploader" type="file" name="curriculum" style="display:none;"/>
JAVASCRIPT
function uploadCurriculum(file) {
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//FormData will contain the post params
var form = new FormData();
xmlhttp.onreadystatechange = function() {
//Handle response if everything is right
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//This is the element where i will put my response
var element = document.getElementById('curriculum');
//The response is given in the property responseText
element.innerHTML = xmlhttp.responseText;
//If you response has javascript elements, you need to place them in the header to make client compile them
var scriptElements = element.getElementsByTagName('SCRIPT');
for (i = 0; i < scriptElements.length; i ++) {
var scriptElement = document.createElement('SCRIPT');
scriptElement.type = 'text/javascript';
if (!scriptElements[i].src) {
scriptElement.innerHTML = scriptElements[i].innerHTML;
} else {
scriptElement.src = scriptElements[i].src;
}
document.head.appendChild(scriptElement);
}
}
}
//Put your params in the url if you want to send them by GET
xmlhttp.open("POST", window.appContext + "/controller/action/" + someParams, true);
xmlhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
//add the file to the form to send by POST
form.append('curriculum', file);
xmlhttp.send(form);
}
function handleFileSelect(event) {
handleDragOver(event);
var files = event.target.files || event.dataTransfer.files;
if (files.length > 0) {
parseFile(files[0]);
}
}
function handleDragOver(event) {
event.stopPropagation();
event.preventDefault();
if (event.type == "dragover") {
event.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
addClass(event.target, "hover");
} else {
removeClass(event.target, "hover");
}
}
function showFileSelect() {
document.getElementById('curriculumUploader').click();
}
function parseFile(file) {
if (file != null && file.size > 0) {
uploadCurriculum(file)
} else {
console.log('Invalid file');
}
}
// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
if (dropZone != null) {
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener("dragleave", handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
dropZone.addEventListener('click', showFileSelect, false);
}
var inputelement = document.getElementById('curriculumUploader');
inputelement.addEventListener('change', handleFileSelect, false);
CSS
#drop_zone {
padding: 15px;
text-align: center;
border: 1px dashed #4b9df2;
color: #4b9df2;
cursor: pointer;
transition: all linear 0.2s;
}
#drop_zone.hover {
border: 1px dashed #C99F23;
color: #C99F23;
}
来源:https://stackoverflow.com/questions/10150370/grails-asynchronous-file-upload