Ext.Ajax.request callbacks never called when isUpload is true - javascript

I'm using ExtJS to make a form that generates a report from the data in the database in CSV format. After the user chooses a simple range of dates to extract the data and submits, running the following code :
var frm = document.createElement('form');
frm.id = 'frmDummy';
frm.name = id;
document.body.appendChild(frm);
Ext.MessageBox.wait('Generating CSV File ...');
Ext.Ajax.request({
url: 'csv_extract_ajax.php?start_time='+txtDateFieldFrom.getRawValue()+'&end_time='+txtDateFieldTo.getRawValue(),
method : 'POST',
form: Ext.fly('frmDummy'),
isUpload: true,
success: function(o, r, n){
Ext.MessageBox.updateProgress(1);
Ext.MessageBox.hide();
},
failure: function(o, r, n){
Ext.MessageBox.updateProgress(1);
Ext.MessageBox.hide();
},
callback: function(o, r, n){
Ext.MessageBox.updateProgress(1);
Ext.MessageBox.hide();
},
scope: this
});
The associated php file simple outputs a CSV string, working file.
Since the isUpload is true, it seems that the callback is never returned to the user. As soon as I remove it, the callback is called but the file is not uploaded to the client.
The problem now, everything is working perfectly but the MessageBox never disappears since the callbacks are never called (success, failure or callback)
Any idea ? :P
Additional info:
PHP header :
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: private");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=$filename");
header("Accept-Ranges: bytes");

This is an excerpt from Ext.Ajax.request documentation:
isUpload : Boolean (Optional) True if
the form object is a file upload (will
usually be automatically detected).
File uploads are not performed using
normal "Ajax" techniques, that is they
are not performed using
XMLHttpRequests. Instead the form is
submitted in the standard manner with
the DOM element temporarily
modified to have its target set to
refer to a dynamically generated,
hidden which is inserted into
the document but removed after the
return data has been gathered. The
server response is parsed by the
browser to create the document for the
IFRAME. If the server is using JSON to
send the return object, then the
Content-Type header must be set to
"text/html" in order to tell the
browser to insert the text unchanged
into the document body. The response
text is retrieved from the document,
and a fake XMLHttpRequest object is
created containing a responseText
property in order to conform to the
requirements of event handlers and
callbacks. Be aware that file upload
packets are sent with the content type
multipart/form and some server
technologies (notably Java EE) may require
some custom processing in order to
retrieve parameter names and parameter
values from the packet content.
As you can see, upload request is returned via IFRAME and only emulates standard AJAX response, so that callbacks are not called.

Try changing:
l: 'csv_extract_ajax.php?start_time='+txtDateFieldFrom.getRawValue()+'&end_time='+txtDateFieldTo.getRawValue(),
to
l: 'csv_extract_ajax.php?'+ Ext.urlEncode({ start_time: txtDateFieldFrom.getRawValue(), end_time: txtDateFieldTo.getRawValue() }),

Is there any error displayed in the page?
What is the content type of response?
The extjs api doc says it should be set to "text/html".
If it still not working you can try to put a breakpoint in doFormUpload(). This method is present in connection.js. Inside this you can find a inner method called cb(), this method will be called once the server returns. You can start debugging from there.
all the best.

As soon as I remove it, the callback
is called but the file is not uploaded
to the client.
Setting isUpload to true means you are gonna to upload file from client to server, but this is not your case, I'm afraid.

Do you noticed this in every browser, or just in a particular browser?
Firefox 3.5 (with Firebug installed) appears to have a bug that means that readystatechange does not get updated which would mean that callbacks do not get invoked.

If you don't have a file to upload, why are you setting isUpload to true?
Also, if you are posting a data to a PHP script and if that script returns a CSV string, why are you trying to send it as attachment? Why not send it as regular response text?

Related

Passing JS variables to a PHP file (using ajax) in order to update SQL table [duplicate]

I have a problem sending data with an AJAX query to a php file, basically I use post request to send some data just for testing it out, the request is successful when I checked with developer tools in Chrome, as I can see the data that was sent , but the variable $_POST[] in php is always null, and don't understand why, because my data was sent to the php file.
Tried all kind of possibilities found on here, non of them will let me to go further, all of them will leave my $_POST[] empty. I modified the values inside the data attribute I added or removed content-type but nothing worked.
Here you have my jQuery code.
$.ajax({
method: "POST",
url: "2.php",
data: { name: 'JohnDoe', age: '19' }
}).done(function( msg ) {
alert(msg);
});
This is my PHP code.
<?php
$user=$_POST['name'];
var_dump($user);
?>
Errors
$user=$_POST['name'];
//ERROR - Notice: Undefined index: name in G:\xampp\htdocs\weather\2.php on line 6
//Expected result is 'JohnDoe'.
var_dump($user);
//this is Null
//Expected result is to contain some data
This are my two results I get in php.
The html and php files are in the same folder.
You are making two HTTP requests.
The first one using JavaScript, where you make a POST request and alert the response.
You can see the data from the response there.
You make the second request by typing the address into the address bar, where you make a GET request and have the response rendered as a webpage.
$_POST contains the POSTed data from the current request, not the data from any previous request.
The data you POSTed when you made the first request is not available when the PHP program runs again using the second request as input.
If you want to access that data then you need to explicitly do something to make it persist. This could be linked to the browser (so different users would not see each others data) — such as in a session or a cookie — or it could be independent of the browser — such as in a database — so every visitor to the site could see the data.

"Unexpected end of JSON input" error on loading JSON file from local file system

Hi I'm trying to retrieve data from a title.JSON file into an index.html file using AJAX calls.Both these files resides in my local file system.I have created a new instance of the chrome and 've set its target property as "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"--disable-web-security --user-data-dir="c:/chromedev"(I'm aware that this is not a good practice. Just trying out a server less way).Below is my code
<h1><a id="headName" href="#">Name</a></h1>
<p onclick="spaLoad()">NameChange</p>
function spaLoad(){
var xhr = new XMLHttpRequest();
xhr.open('GET','title.json',true);
xhr.send();
xhr.onreadystatechange=function () {
//var obj=xhr.responseText;
var obj = JSON.parse(xhr.responseText);
console.log(obj);
console.log(xhr.readyState);
console.log(xhr.status);
console.log(xhr.statusText);
//document.getElementById('headName').innerHTML = obj;
document.getElementById('headName').innerHTML = obj.name;
}
}
title.json
{"name":"stackoverflow","age":"100"}
I get my h1 updated as "stackoverflow" through an ajax call along with the error
Uncaught SyntaxError: Unexpected end of JSON input
at JSON.parse ()
at XMLHttpRequest.xhr.onreadystatechange
Here are my doubts:
1.I hope AJAX is for the communication between the client and the server. Though I have avoided using a server by modifying the browser settings, how did the ajax call work for me?Is it logical?
2.The JSON file contains the data as objects.Then why should I use JSON.parse(responseText)?(JSON.parse() is for converting the string from server into object for client I hope).If i directly give var obj=xhr.responseText;I get undefined.
3.readystate is changing to 4, but status is always 0.Why is it so?How could I resolve it.
Please give a brief explanation of how this server less ajax call works.I'm very new to ajax and is confused with this.
It is because readystate change fires multiple times and you expect it to fire once. You would need to check for readystate to be equal to 4 and the status to be 200 (or zero in your case since you are on the file protocol). Or use the onload and onerror events instead.
And if you still get a parsing error than you need to debug what is being returned.
//see what is returned
console.log(xhr.responseText)
//Look to see if you have hidden characters in the file.
console.log(escape(xhr.responseText))
Parsing errors occur either the file you are loading returns something else like an error page OR it has special hidden characters that cause the parser to choke.

How can we download the dynamically generate file from server?

I want download the file from server (I knew that we can't use AJAX, and serve is Servlet) and which dynamically generate according to the parameters.
Now I have the parameters in format JSON, like:
{"limitTo":"name","searchFor":["AAA","BBB","CCC"],...}
So, how can we send the request to the server with those paraleters? Do we need create some inputs?
Thanks, I found the solution which uses dojo/request/iframe, without window.open
And the code likes :
require(["dojo/request/iframe"], function(iframe){
// cancel the last request
iframe._currentDfd = null;
iframe("something.xml", {
handleAs: "xml",
data : "your json"
}).then(function(xmldoc){
// Do something with the XML document
}, function(err){
// Handle the error condition
});
// Progress events are not supported using the iframe provider
});
And then we can see download window.
Here is an article about dojo/request/iframe

Why jQuery.parseJSON does not parse this valid JSON document in Firefox?

Server returns this JSON document:
{
"username-found": true,
"question-required": true
}
Which successfully passes JSONLint's validity check.
In web browser:
$.post('my_url', {"post":"data"}, function(data) {
data = $.parseJSON(data);
});
The code runs and successfully parses the JSON document in Opera 12 browser, however in Firefox 16, JavaScript error occurs and says "not well-formed".
JQuery is of version 1.7.2.
I cannot see what I did wrong there, do you know?
Edit:
Does it have anything to do with the way server returns the JSON? Here it is:
return new StreamingResolution("text", new StringReader(json.toString()));
uggestion, I might have found the cause. When I did alert(data), Firefox tells me that data is an object, Opera tells me that data is the JSON string.
Solution 1 (Client) - Set DataType in jQuery Request
I think the internals are a bit different in that specific browser version (because jQuery tries to detect the dataType automatically and is doing the parsing internally in the case of a JSON response) and JSON is automatically encoded in FF and not in Opera?
Try to add the dataType so jQuery will handle this (I would prefer that):
$.post('my_url', {"post":"data"}, function(data) {
// data should be an json object here
}, 'json');
It's just a guess.
OR Solution 2 (Server) - Send MIME type
You could also send a correct MIME type from the server so you don't have to set the dataType on the client. Its up to you but I think that would be the correct solution.
Regarding this answer it should be application/json.
Reference
How is the dataType detected automatically in jQuery?
Default: Intelligent Guess (xml, json, script, or html) The type of
data that you're expecting back from the server. If none is specified,
jQuery will try to infer it based on the MIME type of the response (an
XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript
object, in 1.4 script will execute the script, and anything else will
be returned as a string).
Source: http://api.jquery.com/jQuery.ajax/
You can directly use the data object directly ..
No need to use $.parseJSON();
You also have a $.getJSON shortcut method in jQuery. Maybe jQuery automatically uses the best configuration for this case and maybe start working
Here is the $.getJSON documentation

Handling dynamic HTTP Content-Type with jquery Ajax

I have a perl script URL which gives me a ZIP file, it processes the data and dynamically set the Content-Type to 'application/zip' in the http-header.
Perl code looks like this:
WPHTTPResponse::setHeader( 'Content-disposition', 'attachment;filename="test.zip"');
WPHTTPResponse::setHeader( 'Content-type', 'application/zip');
print $result;
In frontend, I am using this script direct in HREF:
Download
But I have a requirement of showing an alert message if $result is NULL in perl script.
What I am thinking is: I will send the file with Content-Type=>application/zip if the $result if not null, otherwise I will send the JSON response with error message that there is no file to download.
For this I would need to dynamically check the content type using JS:
$.ajax({
url: '/script',
data: {....},
success: function(response) {
if(response.contentType == 'application/zip'){
//download using javascript
}
else{
$.parseJSON(response);
alert(response.msg);
}
}
});
I'd appreciate any help.
Although your method should work, this is a case where using using HTTP error codes would probably be a good choice.
Depending on why $result is null one of these should be appropriate.
400 Bad Request
406 Not Acceptable
410 Gone
This would make your code slightly more 'obvious' as you would be using the HTTP status for exactly what it was meant for, rather than re-implementing the exact same thing in a proprietary way in your code. IMHO it would also make your code a bit easier to maintain as it would separate the success from the error.
You can still include JSON as part of the error response, to be able display information about exactly why the request didn't result in any data being returned to the client.
btw I'd avoid using 404 as the error code, even though it is technically the most 'appropriate' code just because it would cause confusion if a real 404 error occurred.
Use HEAD-request for check content size before download.
Client-side:
Attach click-event handler to <a>-element.
On click-event send HEAD-request throw XHR.
On XHR-response check content size.
If size is zero, then show alert and prevent default event handler.
If size is not zero, nothing to do.
Server-side:
Compute content size on HEAD-request.

Categories

Resources