Download the returned PDF from Ajax - javascript

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.

Related

How to create an Ajax GET that behaves like window.location?

I've got a csv that I've been able to retreive using
window.location = "/path/to/mydata", which I understand creates a GET request to that location. Now I'd like to add header params, so I do something like this...
$.ajax(
url:"/path/to/mydata",
method: "GET",
headers: {"my-header": "..."})
.done((data){
// "data" is now a string of my csv data
console.log(data)
});
When I simply do window.location chrome somehow detects that I got a CSV file back and saves the contents locally to My Downloads. I'm not sure how to do that with the ajax done callback function, or if there is an ajax parameter that I could use that does it automatically.

How to make local file download

I want a local file (on the server) to be downloaded by the user. The user first kicks off the file creation by pressing a button and once the file is ready, he should be able to clock on a link or a button to download the file.
Creating the file has not been a problem, as i simply send an AJAX call to my backend which looks like
#POST
#Path("/createFile")
#Produces("application/text")
#Consumes("application/json")
public String createFile(String argsFromPage) {
/*File creation code here*/
return "Path of file created";
}
Now, that the file is created, all I want is to create a link which the user can click and download this file. For now, the file can be either a binary or a CSV file. I have made several attempts but without any success
<button onclick='create_file()'>Create</button>
function create_file() {
$.ajax({
method : "POST",
url : ".path/to/backend/service",
contentType : "application/json",
data : JSON.stringify({
param1 : val1
})
}).done(function(data) {
console.log(data);
});
}
now once the file has been created, is it possible to create a download link? Better still, is it possible to invoke the download as soon as the file is created? Should this be done in the browser, or the back end?
Follow Up
Once the file has been downloaded, how can i delete it form the server? Is there any way to endure that the file download has been completed?
To create a link to the file you can just create an a element in the DOM within the done() handler. Try this:
function create_file() {
$.ajax({
method: "POST",
url: ".path/to/backend/service",
contentType: "application/json",
data: { param1: val1 } // I assume 'val1' is declared in a higher scope?
}).done(function(path) {
$('#someContainer').append('Click here to download');
});
}
Note that I removed the manual JSON.stringify call as jQuery will do this for you. Also note that it would be better to return JSON from the AJAX request as it avoids issues with whitespace, although the above should still work given the code sample you provided.

Multipart or base64 for AJAX file uploads?

I'm writing a single page application with EmberJS and need to upload a few files.
I wrote a special view, that wraps the file input field and extracts the first file selected. This lets me bind the File-Object to a model-attribute.
Now I have to choose.
I can write a special file transform, that serialises the File-Object to base64 and simply PUT/POST this.
Or I can intercept the RESTAdapter methods createRecord and updateRecord to check every model for File-Objects and switch the PUT/POST requests to multipart/form-data and send it with the help of FormData
Does one of these directions pose significant problems?
I've had to evaluate the same concern for a Restful API I'm developing. In my opinion, the most ideal method would be to just use the RESTAdapter with base64 encoded data.
That being said, I had to use the multipart/form-data method in my case, because the data transfer is 30% higher when you base64 encode the file data. Since my API would be have to accept large (100MB+) files, I opted to have the POST method of the API to receive multipart form data, with the file and json data being one of the POST variables.
So, unless you need to upload large files like in my case, I'd recommend always sticking to the REST methods.
Just ran into this myself, and ended up using a simple jQuery AJAX call using the FormData object. My multi-select implementation (where one can drop multiple files at once) looks like this:
filesDidChange: function() {
// Get FileList
var $input = this.$('input'),
fileList = $input.get(0).files;
// Iterate files
for (var i = 0; i < fileList.length; i++) {
var file = fileList[i],
formData = new FormData();
// Append information to FormData instance
formData.append('attachment[title]', file.name);
formData.append('attachment[file]', file);
formData.append('attachment[post_id]', this.get('post.id'));
// Send upload request
Ember.$.ajax({
method: 'POST',
url: '/attachments',
cache: false,
contentType: false,
processData: false,
data: formData,
success: makeSuccessHandler(this),
error: makeErrorHandler(this)
});
}
// Notify
this.container.lookup('util:notification').notify('Uploading file, please wait...');
// Clear FileList
$input.val(null);
},

Ext.data.JsonP.request always going to failed function?

I am doing application in Extjs, i am calling Ext.data.JsonP.request. In below code url path will come dynamically generate by appending name to base url of pdf. But Here i am hard coded. I am passing this url and testing jsonp request. if this url returns success i can write code success logic else failure, but here always going to failure method. also i have tried Ajax.request but no use. Some time i will get pdf path but that pdf is not in server that time i need showcase alert message like pdf is not found. Can tell me how can achieve this one? is it possible by calling jsonp request or any other method? Thank you
here is my code:
Ext.data.JsonP.request({
url: 'http://jmlr.csail.mit.edu/papers/volume10/mannor09a/mannor09a.pdf',
method: 'GET',
params: {
//fileID: feed_id, //this.form.getComponent('file').value,
},
failure: function () {
alert('failed !');
},
success: function () {
alert('success!');
}
});
Are you sure, that you need ajax to get pdf file? If you want to display this file to user, you can just put direct link to this file (without ajax or other tricks) and browser will show it.
Hard to understand, what do you want to get in the success function.
My recommendation to use plain link (you still can generate it dynamically to user)
Link
against using JSONP in this situation :)

How to open a popup and send a JSON object to it

I want to send a JSON object to a PHP file while my script opens that PHP file in a new popup window. Is it possible to send it via POST method (by jQuery or without it)?
If not, how do I convert JSON to a URL encoded string? Is there any JavaScript function?
You may create a form (on the fly) with an input (where you fill the value with the JSON) and a target-attribute regarding to name of the popup (second parameter of window.open()).
Then send this form.
Open the popup: var popup = window.open(...)
Assign the json object to a new variable in the new window: popup.json = ...
Use the variable json in your popup (it will be accessible as window.json or just json from JavaScript code running in the popup).
There's a JSON encoder/decoder that looks like it would do the job. You could call this to encode your object before adding it to your querystring.
Example
alert(JSON.encode([0,1,false,true,null,[2,3],{"some":"value"}]));
// [0,1,false,true,null,[2,3],{"some":"value"}]
alert(JSON.decode('[0,1,false,true,null,[2,3],{"some":"value"}]'))
// 0,1,false,true,,2,3,[object Object]
You can use the Ajax API to do so... In the Ajax API, you can specify the data property and set it a JSON, and it will send the data to the server based on the type you have set, that is, GET or POST.
For example:
$.ajax(
{
url: url, // Your post URL
type:"POST", // or GET
data: {a:1} // In your case, your JSON object
success:function(response){}, // Function that will be called when your posted URL responds
crossDomain: true, // If it's a cross-domain request
dataType: "json" // Response datatype: JSON, text, HTML, XML, etc.
}
);
One thing to note is that if your response needs to be processed, you need to get around the same origin policy set by the browser. Please read about the same. You could use something called JSONP. It's part of the Ajax API.
I hope this is what you want.

Categories