I need to make an AJAX call from a page, sending some JavaScript data to a PHP file, which creates a file based on that data. I then want this file to be downloaded by the user.
So is it an option, to make a force download of a file created by PHP (specifically PHPExcel in my case) via an AJAX request?
The code shown below does not yet send any JavaScript data, but does generate a file.
This is my PHP script, which creates a file using PHPExcel:
public function renderTasksToExcel($tasksData){
$objPHPExcel = new PHPExcel();
// Set properties
$objPHPExcel->getProperties()->setCreator("TRW");
// ...
// Add some data
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->SetCellValue('A1', 'Hello');
// ...
// Rename sheet
$objPHPExcel->getActiveSheet()->setTitle('Simple');
// Save Excel 2007 file
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
$file = '/export.' . date('Y-m-d-H-i-s').'.xlsx';
$objWriter->save($file);
// hotovo
return $this->sendResponse(new FileResponse($file));
}
And this is AJAX call:
$.ajax({
type: "POST",
url: {plink Tasks:tasksToExcel},
data: ajaxData,
success:function(data){
$('#download').html(data);
}
})
same with mine. but i already solve this problem,try this:
use this in your php:
$objWriter->save('export/FileName.xls');
and use this in your ajax call:
$.ajax({
type: "POST",
url: {plink Tasks:tasksToExcel},
data: ajaxData,
success:function(data){
$('#download').html(data);
var zz=document.createElement('a');
var data_type = 'data:application/vnd.ms-excel';
zz.href ='htp://localhost/bengkel/backend/export/FileName.xls';
zz.download='FileName'+'.xls';
zz.click();
}
})
simple concept,ajax cant download. then,save *xls file,and then download that file with JS.
sorry im junior programmer and my bad english..
hope this help you,good luck :)
Related
I'm trying to allow a user to upload a 15 MB file to my web, from there that file should be posted to a web service of mine, receive the response (a pdf file) and serve that to the user so he can download it.
However, I'm ending in a URL like this with no prompt to download anything, just a 404 error: http://localhost:10080/Download?file=%PDF-1.4%%EF%BF%BD%EF%B (etc)
Some points:
First I will compress the file
Because of the previous point, I'm using Ajax to post the file
Ajax code
$("#file").on("change", function(evt) {
var files = evt.target.files;
/* Create zip file representation */
var zip = new JSZip();
/* Name, content */
zip.file("data.zip", files[0]);
zip.generateAsync({
compression: 'DEFLATE',
type: 'blob'
}).then(function(zc) { // Function called when the generation is complete
/* Create file object to upload */
var fileObj = new File([zc], "compressed-data");
/* form data oject */
var formData = new FormData();
/* $('#file')[0].files[0] */
formData.append('attachments', fileObj);
$.ajax({
type: "POST",
url: $("form#data").attr("action"),
data: formData,
contentType: false,
processData: false,
success: function (returnValue, textStatus, jqXHR ) {
window.location = '/Download?file=' + returnValue;
}
})
Python Web Code
def post(self):
attachments = self.request.POST.getall('attachments')
#handle the attachment
_attachments = [{'content': f.file.read(),
'filename': f.filename} for f in attachments]
# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt.adapters.appengine.monkeypatch()
#web service url
url = 'http://localhost:8080'
files = {'attachments': _attachments[0]["content"]}
resp = requests.post(url, files=files)
self.response.headers[b'Content-Type'] = b'application/pdf; charset=utf-8'
self.response.headers[b'Content-Disposition'] = b'attachment; filename=report.pdf'
self.response.out.write(resp.content)
Python Web Service Code
#app.route('/', methods=['POST'])
def hello():
#the attached ZIPPED raw data
f = request.files["attachments"]
#to unzip it
input_zip = ZipFile(f)
#unzip
data = [input_zip.read(name) for name in input_zip.namelist()]
generator = pdfGenerator(io.BytesIO(data[0]))
return generator.analyzeDocument()
The pdf generator uses Reportlab, writes the pdf over a
io.BytesIO() and returns it with output = self.buff.getvalue()
1.- What am I doing wrong with the window location thing?
2.- Am I doing something wrong with the file type?
I'm two days into this, now I need help.
Thanks.
However, I'm ending in a URL like this with no prompt to download anything, just a 404 error: http://localhost:10080/Download?file=%PDF-1.4%%EF%BF%BD%EF%B (etc)
That's what you're asking in window.location = '/Download?file=' + returnValue;, you redirect the user to /Download.
When you call your service, you should ask for a Blob response. Then, use saveAs (or FileSaver.js, a polyfill) to trigger the download.
As far as I know, $.ajax doesn't let you download binary content out of the box (it will try to decode your binary from UTF-8 and corrupt it). Either use a jQuery plugin (like jquery.binarytransport.js) or use a xhr directly.
$.ajax({
type: "POST",
url: $("form#data").attr("action"),
data: formData,
contentType: false,
processData: false,
dataType: 'binary', // using jquery.binarytransport.js
success: function (returnValue, textStatus, jqXHR ) {
// Default response type is blob
saveAs(returnValue, "result.pdf"); // using FileSaver.js
}
})
Our project uses the SPA's "Hot Towel" template, which includes the Durandal framework.
We're also using Telrik's Kendo UI, and I'm having trouble using the DataSource widget to simply read in a local json formatted file from my project folder.
I'd like to read a test data file from either my "app\app_data\" folder to my "app\viewmodels" folder.
Of course if I hard code my data into the js function it works fine. Like this for example:
var ds2 = new kendo.data.DataSource({
data:
[{ data here" }];
});
ds.read()
However, trying to read from local project folder will not work. I'd like to simply mockup some test data while developing.
Your advice would be appreciated.
var ds = new kendo.data.DataSource({
transport: {
**read**: {
url: "PositionsTestData.json", // "../app/app_data/PositionsTestData.json",
dataType: "json"
}
}
});
ds.read(); // in console, ds.data is showing 0 records.
I'm also trying a std jquery ajax get:
var jq = $.ajax({
url: "app/viewmodels/PositionsTestData.json",
type: "get",
dataType: "json",
contentType: 'application/json'
});
I'm seeing 404 NOT FOUND in Chrome inspector tool, under Network tab.
thank you.
Bob
Attaching .done .fail and .always to ajax calls is now doable for me - it is "easy" when the script is at the bottom of the html page.
Now I want to create generalized ajax functions that I can use just by including a js file in the header. I've been successful with ajax functions that read data from server (.done always works). I'm having problems when I just write or update data to the server (no return of data). Here are the specifics-
Standard ajax add/update call that always works - in script tags at bottom of page.
$.ajax({
type: 'POST',
url: 'supdateajaxfunctiontestbackend.php',
data: {localid: localid,
firstname: firstname,
lastname: lastname}
}).done(function(){ alert('Done with Add/Update!'); });
If I create a function at the bottom of the page, or add the function to a js file, this add/update always works.
function generalWriteAjax(filetocall, datatosend) {
$.ajax({
type: 'POST',
url: filetocall,
data: datatosend
}).done(function(){ alert('Done with Add/Update!'); });
}
I would like to detach the .done from the function, and call the .done when attached to a separate function/object. The following code works fine WHEN THERE IS DATA RETURNED FROM THE SERVER. (a separate generalReadAjax function that asks for server data). The done is attached to an object that is returned from the server (This concept I found here on Stackoverflow).
backenddata = generalReadAjax('readtesttablebackend.php');
displayData(backenddata);
backenddata.done(function(){ alert("Done with read!"); });
});
I have tried all of the following with the WRITE/UPDATE only function, and none of them work.
generalWriteAjax(filetocall4update, datatosend4update).done(function(){ alert('Done function'); });
generalWriteAjax(filetocall4update, datatosend4update).when(function(){ alert('Done function'); });
generalWriteAjax(filetocall4update, datatosend4update).then(function(){ alert('Done function'); });
generalWriteAjax(filetocall4update, datatosend4update);
createdonealert = generalWriteAjax(filetocall4update, datatosend4update);
createdonealert.done(function(){ alert('Done function'); });
createdonealert.when(function(){ alert('Done function'); });
createdonealert.then(function(){ alert('Done function'); });
So obviously, there is a difference in the way the promise is handled between a "go get me data" and "here is data, please store it".
I even put an echo "Done"; at the bottom of the update php file just to return something, and still no luck.
I've searched this site and google with combinations of:
ajax .done attach add update not working promise
and have found nothing that deals with my specific example.
Can someone give me some guidance?
I thank you in advance.
Well, no one has responded, and I've learned a bit by hacking on this for the last day. Here are some things I THINK I've learned:
If you create a general callable function using ajax, it does not act the same as an "inline" ajax - you do not get the same callback actions as you do when the ajax code is at the bottom of an HTML page between script tags.
If you return something from the server, the ajax function acts similarly to when it is between script tags.
If you DO NOT return data from the server, the ajax function does NOT act the same as when it is inline.
So what I've done is on all php files that are "write/update" only (no data returned), I add a little code to the bottom of each php file that returns a small amount of json "junk". With this "junk" the ajax function acts like a regular ajax call between script tags at the bottom of the page.
It's a kludge, but it works. Here is the code at the bottom of a read/update php file that normally would NOT return anything. It now returns a json array regarding "John":
$json = array('firstname' => 'John');
echo json_encode($json);
Here is the function in the attached js file:
function generalWriteAjax( filetocall, datatosend ) {
return $.ajax({
type: 'POST',
url: filetocall,
data: datatosend,
dataType: 'json'
});
}
Here is the code on the page that calls the .js function:
$("#clicktoupdate").click(function(e) {
var localid = $('#idnumber').val();
var firstname = $('#updatefirstname').val();
var lastname = $('#updatelastname').val();
var filetocall4update = 'supdateajaxfunctiontestbackend.php';
var datatosend4update = {localid: localid, firstname: firstname, lastname: lastname};
generalWriteAjax(filetocall4update, datatosend4update).done(function(){ alert('Done inline'); });
});//end of update click
I wish I understood the details, but this is an empiric solution that works.
Comments from the experts would be nice.
Thanks for looking!
I'm make an ajax call to run a file:
var data = 'index=exp' + index;
var go_url = get_bloginfo('template_url') + '/form/exp.php';
$.ajax({
url: go_url,
type: "GET",
data: data,
cache: false
});
The file "exp.php" inserts a new row in mysql database and it works.. but with the ajax call nothing happens. As if he did not open the link.
I think you should add 'add_action' for functions in wordpress
like
function yourfunction(){
...
}
add_action('wp_ajax_your_function', 'yourfunction');
add_action('wp_ajax_nopriv_your_function', 'yourfunction');
and in your jquery you can call 'your_function' instead of php file
Is the ajax being called?
Try putting it inside of document ready.
$(document).ready(function() {
// put all your jQuery goodness in here.
});
I have a problem posting file via ajax jQuery function. I have something like this:
$('#my_form').submit(function() {
var serialized = $(this).formSerialize();
var sUrl = "xxx";
$.ajax({
url: sUrl,
type: "POST",
data: serialized,
success: function(data) {
$(".main_container").html(data);
}
})
return false; // THIS return statment blocks sending file content
});
When I remove return false statement everything is okey, server side gets the file content and etc, but when it's there (i monitor with firebug) that this posting sends only file name. What can be wrong?
P.S. - I need this return false statement, because I want to manipulate return data myself.
First stop — the manual.
Data from file select elements is not serialized.
From http://api.jquery.com/serialize/
You can't read local files with JS, so you can't submit them using XMLHttpRequest.
jQuery - receiving the $_FILES array using $.post lists a number of alternative approaches.