JQuery Ajax call for PDF file download - asp.net-mvc-3

My question is similar to Download and open pdf file using Ajax
But not exactly the same , the reason I want an JQuery ajax is that my file is being generated dynamically from the data which would be fetched from the same page.
So basically I have a Json Object which needs to be sent to the server which would dynamically generate a file and send it back to the browser.
I would not like to use query strings on an anchor with my Json object stringyfied ,
as I think it would be a potential threat as query strings have character restrictions ( am I right here ?).
Please let me know If my workflow is right or I can achieve the same thing thing using a different flow.

You should not use AJAX to download files. This doesn't work. This being said you are left with 2 options:
action link and query string parameters or if the download must be trigerred at some specific javascript event you could also set the window.location.href to the action that is supposed to generate the PDF file and pass query string parameters to it.
or if you are afraid that you have lots of data to pass to the controller action that will generate the PDF to download you use a <form> with method="POST" and inside you use hidden fields to store as much parameters and data as you like:
#using (Html.BeginForm("download", "home"))
{
... hidden fields containing values that need to be sent to the server
<input type="submit" value="Download PDF" />
}

Instead of making one more ajax call in your page you can use anchor tag and php force download to perform pdf download
HTML
Download pdf here
PHP
<?php
$fullPath = $_GET['fileSource'];
if($fullPath) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
header("Content-type: application/pdf"); // add here more headers for diff. extensions
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
if($fsize) {//checking if file size exist
header("Content-length: $fsize");
}
readfile($fullPath);
exit;
}
?>
I am checking for file size because if you load pdf from CDN cloudfront, you won`t get the size of document which forces the document to download in 0kb, To avoid this i am checking with this condition
if($fsize) {//checking if file size exist
header("Content-length: $fsize");
}
I too was struggling with this problem, above code worked for me I hope it helps

I have a very sure answer. You can't download PDF file while using the ajax request to server. So instead of that you should use html actionlink. for example
#Html.ActionLink("Convert Data into PDF", "PDFView", null, new { #class= "btn btn-info" });
Above code will generate a link button and you can access Action Method of controller. Also you can use any technique to return PDF file from controller for example you can return PDF file using FileResult class.

Related

fineuploader image uploads include caption with uploaded files

I have a legacy app that has five separate file uploads for a single DB record. Beside each file upload there is a field to enter a caption for the uploaded file.
I am considering replacing the whole lot with a fineUploader gallery and allow up to ten files to be uploaded.
However, it was useful on the old system to have a caption with each image for the ALT tag of the image when it comes to web display.
I could address this with multiple single file uploads using fineuploader and a caption field for each but I want to get away from having so many on the page.
I see there is an option to change the file name during upload so that might be an option but that could lead to very long/messy file names and may cause issues with accents and other characters.
Can anyone suggest a good approach?
I would suggest considering you use the built-in edit filename feature, as this seems most appropriate to me and will certainly be the simplest approach.
Another approach involves the following:
Add a file input field to your Fine Uploader template. This will hold the user-entered caption value. You will likely need some CSS as well to make this look appropriate for your project.
Initialize Fine Uploader with the autoUpload option set to false. This will allow your users to enter in captions and then upload the files by clicking a button (to be added later).
Register an onUpload callback handler. Here, you will read the value of the associated file's caption stored in the text input and tie it to the file with the setParams API method.
The file list portion of your template may look something like this:
<ul class="qq-upload-list-selector qq-upload-list" role="region" aria-live="polite" aria-relevant="additions removals">
<li>
...
<input class="caption">
</li>
</ul>
And your Fine Uploader code will contain this logic (important but unrelated options such as request.endpoint and element left out to maintain focus on your question):
var uploader = new qq.FineUploader({
autoUpload: false,
callbacks: {
onUpload: function(id) {
var fileContainer = this.getItemByFileId(id)
var captionInput = fileContainer.querySelector('.caption')
var captionText = captionInput.value
this.setParams({caption: captionText}, id)
}
}
})
Your server will receive a "caption" parameter with the associated value as part of each file's upload request.

Content-Disposition inline filename issue with IE

I am displaying a pdf in browser with inline from API using an aspx page.
While saving the pdf using Chrome/Firefox, takes the filename from header("Content-Disposition", "inline;filename=xyz.pdf")
But while saving the pdf using IE it does not reads the filename from header("Content-Disposition", "inline;filename=xyz.pdf"). instead it takes the aspx name.
Technical details
I have an xyz.aspx page.
The xyz.aspx page will invoke an API for a document.
Then the downloaded document from API will transferred to browser with inline to display the pdf document.
Am setting the response header as below and writing the file bytes.
HttpContext.Current.Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "inline;filename=\"" + Name + "\"");
HttpContext.Current.Response.ContentType = "application/pdf";
Issue:
While saving the opened pdf in IE it takes xyz.aspx instead of the name from header.
Requirement:
While saving the pdf using IE, it need to save with the name of pdf.
I googled so much, as every one tells its IE behavior. I hope some one knows a solution.
Note: I have to display the pdf in browser and then save. Not to download using "attachment"
It is true some versions of IE can't handle ("Content-Disposition", "inline;filename=...")
This is because filename=... was originally intended for the attachment disposition. Not all browser-based PDF viewers can handle it.
The only solution I see is to allow access via a different url.
Suppose you have a route to the pdf like: /pdf/view. If you change it to /pdf/view/filename and you configure your application to handle this route in the same way as /pdf/view your problem is solved.
You can also re-write the download url on the webserver.
Depending on your webserver you have various ways of doing this.
I have also tried with all kind of headers and methods.
In the end, my solution was
private FileResult ReturnStreamAsPdf(string fileName, Stream stream)
{
ContentDisposition cd = new ContentDisposition
{
FileName = fileName,
Inline = true // false = prompt the user for downloading; true = browser to try to show the file inline
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("X-Content-Type-Options", "nosniff");
return new FileStreamResult(stream, MediaTypeNames.Application.Pdf);
}
and the Route Attribute on the method:
[Route("api/getpdfticket/{ticketnumber}")]
public async Task<FileResult> GetPdfTicket(string ticketnumber)
And the href:
href="#($"/api/getpdfticket/{product.TicketNumber}.pdf")"
It seems like Microsloft is still inventing their own standards:
http://test.greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf
PDF Handler : content-disposition filename

How to pass AJAX POST data to jQuery nyroModal?

Ealier I tried using same functionality with colobox but could not success, now I'm trying to use nyroModal and trying to send ajax data using post method with iframe. But its not going through. Here is the code which I have tried:
var src = "this is test data';
$.nmManual('try_python.php',{
callbacks: {
initFilters: function(nm) {
nm.filters.push('link');
nm.filters.push('iframe');
},
ajax:{data:'code='+src, type:"post"}
}
});
I'm able to open iframe and content from try_python.php is properly displayed in the frame but passed data is not accessible to try_python.php.
I will really appreciate you for any input in this regard.
Kind Regards
Mohtashim
I could not success in posting my content using POST method but I found a workaround where did the following:
(a) Saved my content in a hidden <div id="source" style="display:none;">...</div>
(b) Access this content from the iframe window upon successful load using the following:
var code = window.parent.$("#source");
and this is what I wanted to have....May be it will help many others. If you find a solution to pass direct content using post method kindly share.

Codeigniter instance and external library object: authentification

I will try to be as clear as possible to explain my problem. If not, tell me !
Mywebapp is based on Codeigniter. In it, I did a controller in order to show images uploaded by the users. By this way, the images can only be seen by members or authorized people and are not public like in facebook for example (image addresses are just hashed but are public).
I also use the mpdf library to generate a pdf from the content of a web page. To use it, I have in the third party directory the mpdf library. To be able to use it with my formatting, I put in the library directory (in application directory) my mpdf library (just to be able to use it from different controller). I have a pdf controller which is called from the view where I want to generate the pdf.
So the process is : I call a function of the pdf controller from my view. In this function, I call a function of my mpdf library which create a mpdf object (the third party class) and generate the pdf.
The generation of the pdf works great. The only I had is for the images. I explain. In my html document, the image are embedded like that :
<img src="http:localhost/www/myapp/library/image/hashed_name_of_the_image" alt="" />
The image function of the library controller retrieve the image and shows it. But in this function, I can protect or not the access to run it. For example, to force to be a logged user to see an image (if($this->session->userdata(‘logged’) == true)).
If there is no restriction, the generated pdf contains the images. Cool :).
But if I put a restriction, it doesn't. I understand that the mpdf object is the one which is asking to image function to show the image. So the verification failed.
I tried to use a config parameter on the CI instance object before I call the pdf function. For example, set to true a "pdf_conversion" and the conversion finished, set it back to false.
But it doesn't work. When I check the value in the image function, it's still false... It's like the config value is not change for all object but only for th pdf object which has changed it.
Is there a way to do what I want to do ??? With config parameter or anything else !!! I think I misunderstood something but don't know what !
thanks by advance for answers
Bastien
You problem is that then the library "calls" the image function, it is not logged in. So your controller code denies access.
There are two things you can do:
Move the code that generates/gets the image form the controller into a new library. then call that library from the controller and from the PDF library. This is the preferred way.
In the "image" action, find a way to check if the request is coming from the PDF library. Best guess is to look for something in the HTTP headers the PDF library sends. Anyway this is not very secure since HTTP headers can be "faked".
OFF TOPIC: Is there a reason you server the image from a controller action instead of by directly referencing the image file?
CLARIFICATION ON SOLUTION 1
So you'll have a library image.php that looks like this
class Image {
...
function get_image($hash){
[code for getting the image here]
}
...
}
In the controller:
function image($hash) {
$this->load->library('image');
if (if($this->session->userdata(‘logged’) == true)) {
$image = $this->image->get_image($hash);
[send it to the browser]
}
}
In the PDF library
function export($hash) {
$ci =& get_instace();
$ci->load->library('image');
[do pdf stuff]
$image = $ci->image->get_image($hash);
$this->add_image($image);
[do more pdf stuff]
}
This is the idea, the actual details of the implementation are up to you.

Go - How to load a new html form

After processing a jQuery Ajax Post from an HTML form successfully within a Go program, how do I load a new form? I first tried sending the form as the response and the Javascript displayed it, but it did not clear the old (existing) form. I then tried within the HTML Javascript to set the URL using "window.location = 'localhost:8088/MaintForm/'". That resulted in a warning from the browser but did not load the form and did not change the URL. I would like to ideally know both methods - via the Go program acting as a server, and via Javascript. If I manually change the URL, the form loads OK. What I am trying to do is receive a response in Javascript (jQuery Ajax), and then request the new form if the response is positive. I would prefer to do this without changing the URL. As I said above, this partially worked.
You would have to put your original form inside a tag, for example a div, and use your JQuery code to replace the contents of that tag with the new form. This way you are not changing the URL.
This is more of a javascript/JQuery question than a go-specific one.
In javascript:
location.href = '/MaintForm/';
In golang, you can use the http.Redirect function, like this:
http.Redirect(w, r, "/MaintForm/", http.StatusFound)
Please note: this appears to be solved by : I just need to do an "document.write(data);" in Javascript. "Data" contains the new HTML.

Resources