Download file via jquery ajax post - javascript

I am trying to export my web page data and download it as excel file. but the download does not start even the response return succeed.
$.ajax({
type: "POST",
url: _url,
contentType: 'multipart/form-data;boundary=SzB12x',
data: json,
});
The responseText something like this:
PK�J;Fxl/theme/theme1.xml�YOo�6����,[r��n;v��i����#-�kJH:�oC{0X7�2��mZ���d��u#�(٦b:M���������{|��^�0t#��*"w$�!0I�[�՚n�i��'����iH� g�,��|�J�!���hRh�h��?r&�L ���߶S��v#���#��׮�"���}��Жt%�hR�t"������+��������u{ނ��0K���oy�9OTWywkAͯ�
���F�� 6*�����[���U���
I think its the file but I cant download it!!
Any help please?
Thanks!

I faced the same issue and successfully solved it. My use-case is this.
Post JSON data to server and receive an excel file.
That excel file is created on the fly and returned as a response to client.
Code:
$("#my-button").on("click", function() {
// Data to post
data = {
ids: [1, 2, 3, 4, 5]
};
// Use XMLHttpRequest instead of Jquery $ajax
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var a;
if (xhttp.readyState === 4 && xhttp.status === 200) {
// Trick for making downloadable link
a = document.createElement('a');
a.href = window.URL.createObjectURL(xhttp.response);
// Give filename you wish to download
a.download = "test-file.xls";
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
};
// Post data to URL which handles post request
xhttp.open("POST", excelDownloadUrl);
xhttp.setRequestHeader("Content-Type", "application/json");
// You should set responseType as blob for binary responses
xhttp.responseType = 'blob';
xhttp.send(JSON.stringify(data));
});
The above snippet is just doing following
Posting an array as JSON to the server using XMLHttpRequest
After fetching content as a blob(binary), we are creating a downloadable URL and attaching it to invisible "a" link then clicking it.
Here we need to carefully set few things at the server side. I set few headers in Python Django HttpResponse. You need to set them accordingly if you are use other programming languages.
# In python django code
response = HttpResponse(file_content, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
Since I download xls(excel) here, I adjusted contentType to above one. You need to set it according to your file type.

Try to use a hidden form to submit the request.
When a user submits an HTML form, all the data entered into the form by the user is sent as either a GET or POST request to the URL specified in the “ACTION” attribute of FORM.
<FORM action="http://www.labnol.org/sendmail.php" method="post">
...form contents...
</FORM>
In the above example, an HTTP POST request is issued to the sendmail.php script on form submission. You can add target=”_blank” to the FORM tag to process the request in a new window.
However, if you would like to submit a FORM on the page in the background without directing the browser to another page (document.location.href changes on form submit), you have two options:
Option #1. You can either create an invisible IFRAME inside your HTML page and set that as a target for the Original FORM. This will submit the form but without reloading the parent window.
<FORM action="http://example.com/script.php"
method="POST" target="hidden-form">
...form contents...
</FORM>
<IFRAME style="display:none" name="hidden-form"></IFRAME>
Option #2: There’s another method that allows you create custom payloads before submitting the form. Unlike the IFRAME based form submission, the following code makes a standard form submit request and thus your browser location will change and the current page will get added to the browser history. Credit: Rakesh Pai.
submitFORM('http://example.com/script.php', 'POST',
{'name':'digital+inspiration', 'age':'100', 'sex','M'});
function submitFORM(path, params, method) {
method = method || "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
//Move the submit function to another variable
//so that it doesn't get overwritten.
form._submit_function_ = form.submit;
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form._submit_function_();
}
In this link you can find the way to create hidden form and submit it.
enjoy!!

The approach here is directly lifted from https://gist.github.com/DavidMah/3533415.
This approach uses <form> and appends the data with a key. This approach works if the server is already expecting the data as an attribute of the request body, as opposed to being the request body itself. If the data to be uploaded is an object, you could iterate over that object's keys. If the data to be uploaded is an array, either modify the server route or [add idea here].
In browser
// Takes a URL, param name, and data string
// Sends to the server... The server can respond with binary data to download
jQuery.download = function(url, key, data) {
// Build a form
var form = $('<form></form>').attr('action', url).attr('method', 'post');
// Add the one key/value
form.append($("<input></input>").attr('type', 'hidden').attr('name', key).attr('value', data));
//send request
form.appendTo('body').submit().remove();
};
On server
# A Tidbit of sinatra code to respond
# Assume 'url' is a set variable
# Assume 'key' is the key of the value used in the javascript
post url do
data = params[:key]
puts request.body.read
headers['Content-Type'] = "application/octet-stream"
body(data)
end
Example
$.download('/path/resource/', 'data', JSON.stringify(data))

If you just want to download a file, you don't need to use ajax to do it. Actually, you cannot download file using ajax.
You can still do it by making a hyperlink Export request to a server page that responses content-type is application/vnd.ms-excel and content-disposition is attachment.

You can achieve this using an iFrame as well. A sample function:
// append the data to URL
var requestData = {
param1 : "value1",
param2 : "value2",
}
// call the function
downloadFile(<your_URL>, requestData);
function downloadFile(requestURL, data) {
// "transData" is just a user defined variable to encapsulate "downloadIFrame". It can be named anything as required.
var downloadIFrame = window.transData.downloadIFrame = window.transData.downloadIFrame || $("#downloadFileiFrame");
downloadIFrame.attr("src", requestURL + $.param(requestData));
}
// define the iFrame in your HTML and hide it.
<iframe id="downloadFileiFrame" style="display:none;"></iframe>"

$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: yoururlpath,
success: function (response) {
var file = fileName+".xlsx";
window.location = "someFilePath?file=" + file;
}
});

Related

Download the returned PDF from Ajax

I have the following action that returns a PDF:
[HttpPost]
public string GetPDF(string data, float scaleFactor)
{
var result = JArray.Parse(data);
using (var fs = new FileStream(#"c:\pdf\pdftest.pdf", FileMode.Create))
{
MemoryStream ms = (MemoryStream)PdfMaker.CreatePDF(scaleFactor, result, dt);
ms.WriteTo(fs);
return Convert.ToBase64String(ms.ToArray());
}
}
(Ignore the FileStream, that is just for testing)
The result is basically the PDF itself, but it's not getting downloaded, how do I download the output PDF? Should I return something else? I tried using a FileResult, but it's basically the same scenario.
This is the way I'm currently "reading" the file via Ajax:
$.ajax({
type: "POST",
url: "home/GetPDF",
data: { data: JSON.stringify(data), scaleFactor: $("#sf").val() },
success: function (data) {
window.location = "data:application/pdf;base64, " + data;
}
});
Thanks.
Edit:
Used the solution in this post provided by Stephen Muecke
Downloading files via ajax doesn't work because the data ends up in memory in a JS object, not on the user's device. Ultimately you need to use a normal HTTP request and return a FileResult.
However in your case you also need to upload some data first which needs to be added to the PDF before it's downloaded. This is awkward because the download will have to be a GET request triggered in a separate window (because you need the application to remain on the same page afterwards) and supplying that data on the querystring is unlikely to be practical.
A solution to work round this is to have a two-step process:
1) From the browser, upload your data via AJAX to a "EditPDF" action method. In the action method, edit the PDF using the new data, and save it. Then return some sort of unique ID to the client which identifies the correct PDF.
2) When the browser receives the response from the EditPDF method, it grabs the returned ID, and makes a new window.open call to the "GetPDF" action's URL. This action accepts the PDF ID as a querystring parameter, so it's easy to include it in the URL when making the request. This action locates the correct document on the server, and returns it in a FileResult. The browser will download the document, while not affecting the HTML page being browsed.

How to implement a form without using form element?

I have been trying to implement a form without using the form element but no success yet. I have two .php files, file1.php and file2.php
I tried to implement it using the onclick of a button in file1.php, but I can't seem to understand how it works:
function submitData(){
var http = new XMLHttpRequest();
var url = "file2.php";
var params = "lorem=ipsum&name=binny";
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);
}
The function works well, upon the button click it returns the the whole text of file2.php. But this is not what I am trying to achieve. I want this button click to get me to file2.php and from there I can get the parameters and use them further. When I use the form eleement upon clicking the submit button it will get me to file2.php but the above code does not seem to do that. I know I am missing something very obvious here :/ ?
I want this button click to get me to file2.php
I don't know if I undestand you well, but you have to know that XMLHttpRequest() is used to AJAX connections.
AJAX means: Asynchronous JavaScript and XML
Asynchronous menas, that you will be NOT redirected to this file. You will stay in the file file1.php, and at this time the server will run file2.php and give you an answer.
XMLHttpRequest is not used for show you another file. This is useful, when you want to get an answer from a PHP file, without leaving a current page.
Try some jquery like:
$(document).ready(function(){
$('#yourBtnId').click(function(){
//Define all of your form data from input fields, something like:
var formData = {
'name' : $('input[name=inputName]').val(),
//put more here similar to above
};
$.ajax({
type : 'POST', //or get whatever
url : 'urltophpfilewhereyouprocesspost',
data : formData,
dataType : 'json', //or whatever
encode : true
})
.done(function(data){
//do whatever you want
});
event.preventDefault();
});
});

How do you modify a file using JavaScript together with PHP?

I want to add text to a text document using JavaScript and PHP. What would be the best way to do this?
This is possible by using Javascript (front-end) to send an ajax request to the PHP server script that does the operation (back-end).
What you can do is use jQuery.ajax or XMLHttpRequest.
XMLHttpRequest
var url = "addtext.php"; // Your URL here
var data = {
text: "My Text"
}; // Your data here
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
jQuery.ajax
var url = "addtext.php"; // Your URL here
var data = {
text: "My Text"
}; // Your data here
$.ajax({
url: url,
data: data,
method: "POST"
})
Note: There is also the jQuery.post method, but I have not included it.
And, in the PHP file, with the necessary permissions, you can write to the file using fwrite in combination with the other file functions.
<?php
$text = $_POST["text"]; // Gets the 'text' parameter from the AJAX POST request
$file = fopen('data.txt', 'a'); // Opens the file in append mode.
fwrite($file, $text); // Adds the text to the file
fclose($file); // Closes the file
?>
If you want to open the file in a different mode, there is a list of modes on the PHP website.
All the filesystem functions can be found here on the PHP website.
I don't think you can append to a text document unless you are writing server side code.
There are some possible workarounds mentioned in this post:
Is it possible to write data to file using only JavaScript?

JQuery submit form parameters are empty

I am submiting form using $('#myForm').submit my rest service accepts content-type of application/x-www-form-urlencoded, but when using submit() I can't see the request in XHR tab in browser developer tools and the form parameters doesn't reach the Rest service, I could use AJAX post and specify content-type, but Rest service produces octet stream in other words the response contains a downloadable file csv/pdf, what could be the solution to submit form correctly?
Why you are not using $.ajax() with type:"post" ?. you can set header easily there
// Request with custom header
$.ajax({
url: 'foo/bar',
type: 'post',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: {}, // object of your data
success: function(response){
alert(response)
}
});
IF your api response is in octet stream or downloadable file then you have to create virtual form and post it through jQuery, Because through AJAX it is not possible to download file.. When file is download content of current page will remain same event form is posted.
function autoGenerateAndSubmitForm(method, url, post_data) {
var element = document.getElementById("virtual_form");
if(element != null )
{
element.parentNode.removeChild(element);
}
var form = document.createElement("form");
form.setAttribute("id", "virtual_form");
form.setAttribute("style", "display:none;");
//form.setAttribute("target", "_blank"); // remove comment if you want to open it in new tab
form.method = method;
form.action = url;
for(i in post_data)
{
var element=document.createElement("input");
element.value=post_data[i];
element.name=i;
form.appendChild(element);
}
document.body.appendChild(form);
form.submit();
form.parentNode.removeChild(form);
}
Call below function with your poper arguments
autoGenerateAndSubmitForm('POST','your_url',{your_post_data_object:"Here"});
After reading your modified Question usually if the parameters are empty at the API it could be caused by the following.
Form is Not Properly Serialized
The Content Type Specified Is Not what your API is Accepting
When you are using ajax make sure your form does not specify any action and methods else there might be a problem.
The model the API is expecting doesn't match what the form has submitted
When using Ajax change your button type to "button" instead of "submit".

Getting Gravity Forms AJAX Confirmation Message in Javascript Instead of Outputting

I have the Gravity Forms plugin setup in Wordpress, and I am using the AJAX feature on my form. I have it configured to return a Confirmation message upon submission, but I want to grab the value contained in the confirmation message in Javascript instead of having it automatically output onto the form.
I'm not sure how to get grab the Confirmation Message before it is output, or how to prevent it from being output.
It looks like the 'gform_post_render' javascript hook is called right before the message is output, but I'm not sure where to target the confirmation message value or prevent it from outputting.
Is there a way to override the confirmation message output? Or is there a better way to setup Gravity Forms to return a dynamic value through AJAX where I can then determine what to do next?
Thanks!
I ended up getting help from the Gravity Forms support team, and they recommended that instead of using the included AJAX functionality, that I look into the Gravity Forms Web API, specifically the /forms/{ID}/submissions endpoint:
https://www.gravityhelp.com/documentation/article/web-api/#form-submissions
My solution ended up looking something like this:
$('form').submit(function(e) {
e.preventDefault();
// Get Form ID for submission URL //
var formID = $(this).attr('id');
formID = formID.replace('gform_', '');
var formURL = '/gravityformsapi/forms/'+formID+'/submissions';
// Get Form Input Data and Format JSON for Endpoint //
var formArray = $(this).serializeArray();
var formData = [];
$.each(formArray, function(index, data) {
var name = data['name'];
var value = data['value'];
formData[name] = value;
});
formData = $.extend({}, formData);
var data = { input_values : formData };
// AJAX to Submit Form //
$.ajax({
url: formURL,
method: 'POST',
data: JSON.stringify(data)
}).done(function (data, textStatus, xhr) {
// This is the HTML that is output as a part of the Confirmation Message //
console.log(data.response.confirmation_message);
});
});
This allows you to submit the form via AJAX, but then you can chose what to do with the response in the data.response.confirmation_message variable.

Categories