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
Related
Summary of my website: A user fills in some information which after hitting "submit" the information is submitted to the backend via AJAX. Upon the back end receiving the information, it generates a DOCX using the information and serves that DOCX file back to the user.
Here is my AJAX Code in my HTML File
$.ajax({
type:'POST',
url:'/submit/',
data:{
data that I submit
},
dateType: 'json',
success:function() {
document.location = "/submit";
}
})
My Views Function for /submit/ that uses send_file to return file
def submit(request):
#Receive Data
#Create a File with the Data and save it to the server
return send_file(request)
def send_file(request):
lastName = get_last_name() +'.docx'
filename = get_full_path() # Select your file here.
wrapper = FileWrapper(open(filename , 'rb'))
response = HttpResponse(wrapper, content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
response['Content-Disposition'] = 'attachment; filename=' + lastName
response['Content-Length'] = os.path.getsize(filename)
return response
This has worked flawlessly for sometime now. However I started having problems when I increased the amount of "web-workers"/processes from 1 to 4 in my hosting account. Whats happening is a different web-worker is being used to send the file, which is creating a new instance of the site to do that. The problem with that is that the new instance does not contain the file path that is created with the web worker that creates the file.
Like I said, this worked flawlessly when my webApp only had one "web worker" or one process. Now I only have roughly a 50% success rate.
Its almost like a process is trying to send the file before it has been created. Or the process does not have access to the file name that the process that created it does.
Any help would be much appreciated. Thanks!
Code Trying to send path_name through request and then back to the server.
Submit View returning file info back to ajax.
def submit(request):
# Receive DATA
# Generate file with data
lastName = get_last_name() +'.docx'
filename = get_full_path() # Select your file here.
return HttpResponse(json.dumps({'lastname': lastName,'filename':filename}), content_type="application/json")
Success Function of AJAX
success:function(fileInfo) {
name_last = fileInfo['lastname']
filepath= fileInfo['filepath']
document.location = "/send";
}
So can I get the fileINfo to send with the "/send" ?
Each web worker is a separate process. They do not have access to variables set in another worker. Each request could go to any worker so there is no guarantee that you'd be using the file name that was set for a particular user. If you need to transfer information between requests, you need to store it outside of the worker's memory - you could do that in a cookie, or in a database or a file.
So I made a website that displays FPS information stored in a mysql database. For each second of gameplay I have a pair of number(fps)-image(screenshot).
I display the numbers in a line chart made with JavaScript. The behaviour desired is when I click on a bullet in the chart, the screenshot for that particular second is displayed in a div on the page.
I have to mention that the screenshots are stored in the database and they are very low in size. I display then using PHP like this:
$query = "SELECT `image` FROM `logs` WHERE `session_id`=".$_GET['session']." AND `second`=".$second;
$sth = $mysqli->query($query);
$result=mysqli_fetch_array($sth);
if (!empty($result))
echo ' <img id="screen" src="data:image/jpg;base64,'.base64_encode($result['image']).'"/>';
The method I'm using now is when I click on a bullet in the chart (action recorded in JS), I send it as a GET parameter and read it with PHP afterwards, like this:
window.location.href = url + "?second=" + second;
This method obviously will refresh my page. The problem is, the chart I made also has a zoom/scroll option and that resets whenever the page is refreshed, making the experience very bad for the user.
Is there any method to display the screenshots without refreshing the page, for this particular case (where I have to query the database for each click/picture)? Maybe there is a better way of approaching this problem?
Thanks.
I think you've got 2 solutions which are Ajax or Websocket depending your needs.
AJAX
Ajax permit to asynchronously, only when you need, call the server and get datas from an URL which could be a webservice or PHP page... Perhaps, it's the better solution in your case.
To make it easy, you can use JQuery library by donwloading the script and insert it in your HTML :
<script src="jquery-3.0.0.min.js"></script>
To call the server, using JQuery :
$.ajax({
url: url + "/yourphppage.php",
data: "parameter=" + yourOptionelParameter,
async: false,
success: function(data) {
refreshYourChart(data);
},
error: function() {
alert("Your error");
},
contentType: 'charset=utf-8'
});
Or if your prefer pure javascript.
Now, you just have to work on the presentation of your data, on the server side. It could be what you want HTML, TXT, JSON, XML...
Websocket
Websocket is like a permanent tunnel opened between your server and the client. Each side can ask or send datas in real time.
It seems to be a library server side :
http://socketo.me/
And client side, it's very easy :
Nice documentation on mozilla website
Hope it helps. Good luck.
To change a picture source, as I see the easiest way is using an ajax call, so you can send any kind of parameters to your server, and in return your will get your new picture source.
$.get('urlToYourServer.com?parameter=1', function(data){
$('#img').attr('src', data.imgSrc);
})
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.
How can I send just one element from browser to server fast and without reloading browser page?
Is there an AJAX way to do this, that is a NON-FILE method? The opposite of ".load"?
.load works great sending a single element from server to browser without page reload.
How to do the opposite direction?
Browser is JavaScript.
Server is vxworks with windmarks.
PRESENT METHOD THAT WORKS BUT RELOADS PAGE:
Presently, the browser element is and I use submit to send it to the server, but this takes too long and reloads the browser page.
The element's innerHTML contains data formatted as a vxworks WINDMARK.
(When the vxworks server receives this submission, it reads the windmark and copies it to a 'C' string for backend software to process.)
If you're using jQuery and PHP then something like this should work:
JS:
$.ajax('doServerSuff.php?action1=saveLog', function() {
// do stuff after server received the data
});
PHP (doServerStuff.php):
<?php
if ($_GET['action1'] == 'saveLog') {
//do stuff
}
?>
You can get and send data using jQuery. using something like this:
$.post('urlfromserver',browserdata,function(datafromserver){
//do stuff
})
if you let me put a little bit more, it's a good idea to use JSON to send/receive data to/from server. Having that in mind, you can do something like:
$.post('urlfromserver',{browserdata: JSON.stringify(browserdata)},function(datafromserver){
javascriptObject = jQuery.parseJSON(datafromserver)
//do stuff
})
And in your PHP code, it would be as simple as using json_encode to send data to javascript and json_decode to receive data from javascript
UPDATE
Obtaining the data in the server should be as simple as requesting the object via post or get depending on your send method, and parsing the JSON.
In PHP, this is an example of obtaining data using the above code:
$dataFromBrowser = json_decode($_POST['browserdata'])
Use $.post in jQuery to send the data.
The load intruction can also be used to transmit data to the server:
$().load("url", {limit: 25}, function(){
//transmission finished
});
In this example the parameter limit with the value 25 wil be transmitted to the server.
Taken from:http://api.jquery.com/load/
You can simply do with the ajax call like this
$.ajax({
type: "POST",
url: "yourpage.php?id=someValue",
success:function(data){
//do some stuff here
});
I got it working. Here is the corrected JavaScript, from the above answer.
Here is how to change a single element at the server.
This is also an example of how to write to a vxworks windmark string at a vxworks web server, without reloading the page.
NOTE: no URL is specified, so that the same page is used.
$.ajax({
type: "POST",
url: "?general_page_to_MM_data_1_windmark=CCCCCCCCCCCCCC",
success:function(data_from_server){
}});
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?