render pdf using javascript - javascript

In my App I need render a dynamic pdf.
I have an ajax function that call a php function that return a pdf (string format).
Now I render this pdf using data-uri in this way:
window.open('data:application/pdf;base64, ' + response);
...but this works only on chrome.
How can I get that also on firefox?

Hmm how about having your PHP create a temporary local file on the server, and opening that one in your window.open()?
Base64 if very verbose and I am sure you'd get better performance out of just loading it directly from the server (where it actually gets created). Same number of requests, better performance, what could you ask more? ;-)

Related

Is it possible to run a PHP file with HTML on the server

Normally when you have a .PHP file and the client request it, the PHP code is run on the server and the HTML and JavaScript are sent to the client.
Question
Is it possible to have the server request a webpage (local) and run both the PHP code and the HTML with JavaScript on the server? I have created a single .html file that after 3 seconds of processing locally creates the image data for a thumbnail of the given video.
Why
I need to generate a thumbnail for a video. I used shared hosting and my hosting provider doesn't support for ffmpeg. You can, however, generate thumbnails using a canvas and JavaScript. I have already put a lot of pressure on the client. If this is possible, upload and download times would be significantly shorter than using the client.
Attempts
I've tried using file_get_contents(), but it doesn't run the code (Makes sense). Is there a way I could have it open and run for x seconds and then grab the contents?
I've tried using curl to get the file using this function here. I believe it is similar to my previous attempt in that it gets the file contents, but never executes them.
My final attempt was to use new DOMDocument(). I couldn't even get to loading the page though. First, I can't parse it with a video tag. It gives this error:
Warning: DOMDocument::load(): Specification mandates value for attribute controls in
file:\path\to\html\document.html, line: 53 in C:\path\to\php\document.php on line 50
If I were to remove the video tag (which is required), I get errors while parsing my JavaScript. So that attempt also did not work.
Is there a way that I could have PHP process the code (for something on the server) for x seconds before getting the contents? It would allow for time to generate the thumbnail data. If there is another way to do this without using ffmpeg on the server, that would be great.
So as I mentioned in comments, what I'm gonna explain is just an option (not the best one and just answering for your need of running html code!)
Where to do this?
Personally I rather to do this when the video is being uploaded by admin's browser and the best thing is that you can do this as a part of the posting procedure.
So in the page that you want this process to be done, put an invisible iframe like this.
<iframe id="myIframe" style="display: none;"></iframe>
How to begin the process?
I don't know the way you use to upload the videos (and it really is not that important!) but let's assume you want to use formdata. After the video is uploaded you need to know something unique to address the video (let's say an id). So after the video is uploaded, we can recive a code like id:20, initiateThumbnail:true as the result json data. Then we can simply use that hidden iframe to be the browser you've been asking for like this:
$("#myIframe").attr("src","dothething.php?video=20");
Now do what ever you wanted to do in it and change it's content after it's done. Now you need to wait for the result!
$('#myIframe').load(()=>{
let result = $("#myIframe").contents();
// checking result!
});
As you have already thought about, you can handle any errors by processing the result.
Notes
The event listener we used for iframe (iframe.load) fires when you initiate making the thumbnail as well. So be careful with the process of checking result (content of that iframe!)
If you don't use ajax or formdata, simply the action of your form is what I used as iframe.
One question? What happens if network connection goes down during this process? Simple answer! You can check in so many ways that the thumbnail exists or not. If not you can create it once that user requests for it in his browser and upload it back to server and save it for ever (as you did it in admin's panel!)
I think there isn’t another way to generate thumbnail on php server than with ffmpeg.
The only thing you can do, I suppose, is to force canvas generation on page load if you aren’t already doing it.
Anyway you are trying to do something wrong. Php doesn’t evaluate the html code, it’s just a preprocessor and not an interpreter like the browser. You can wait all the time of the world, but you’ll never get the content of the image that only a browser will generate.

How to convert html to base64 and save an image on a server with php?

I have a json file like this:
{"user":{"email":"user#test.com"},
"screenshot":{"blobFile":"<!DOCTYPE html><html lang=\"en\">...</html>"}}
and I want to take a screenshot, using XMLHttpRequest sending data a PHP file.
In PHP file getting request like:
$data = json_decode(file_get_contents("php://input"), true);
$htmlStr = json_encode($data["screenshot"]["blobFile"]); // <!DOCTYPE html><html lang=\"en\">...
so far everything is ok but how to convert this string to the image file and save a server?
I've tried html2canvas in PHP file but not fire.
any ideas?
I'd try to use PhantomJS. It's headless browser, which allows to interact with web pages many ways including making screenshots. It will require some time to understand how to work with it, but it definitely will get a result. Although, PhantomJS sometimes is a headache if your page is quite complicated structured, written using some frameworks like ReactJS, AngularJS, etc.
What it does it renders HTML page with styles including scripts serverside. If you save not HTML string but exact URL with COOKIE and SESSION data and then reconstruct conditions which user had in an opened page when you did a screenshot, it'll do a job.
See example here Screen Capture on PhantomJS

HTML 5 anchor tag download incomplete file?

I am using angular and ASP.NET Web API to allow users to download files that are generated on the server.
HTML Markup for download link:
<img src="/content/images/table_excel.png">
<a ng-click="exportToExcel(report.Id)">Excel Model</a>
<a id="report_{{report.Id}}" target="_self"></a>
The last anchor tag is there to serve as a place holder for an automatic click event. The visible anchor calls the exportToExcel method to initiate the call to the server and begin creating the file.
$scope.exportToExcel = function(reportId) {
reportService.excelExport(reportId, function (result) {
var url = "/files/report_" + reportId + "/" + result.data.Model.fileName;
var dLink = document.getElementById("report_" + reportId);
dLink.href = url;
dLink.setAttribute('download', result.data.Model.fileName);
dLink.click();
});
}
The Web API code creates an Excel file. The file, on the server is about 279k, but when it is downloaded on the client it is only 7k. My first thought was that the automatic click might be happening before the file is completely written. So, I added a 10 second $timeout around the click event as a test. It failed with the same result.
This seems to only be happening on our remote QA server. On my local development server I always get the entire file back. I am at a loss as to why this might be happening. We have similar functionality where files are constructed from a database blob and saved to the local disk for download. The same method is employed for the client side download and that seems to work fine. I am wondering if anyone else has run into a similar issue.
Update
After the comment by SilentTremmor we think it actually may be IIS or some sort of Sever issue. Originally, we didn't think it could be, but after some digging it may be. It seems the instance of the client code is only allowing 7k of data to be downloaded. It doesn't matter what we try to download the result is always the same.
It turns out the API application was writing the file to a different instance of our application. The client code had no idea and was trying to download a file that did not exist. So, when the download link was creating the file it was empty, thus the small file size.

How can I *locally* save an .html file generated by javascript (running on a *local* .html page)?

So I've been researching this for a couple days and haven't come up with anything conclusive. I'm trying to create a (very) rudimentary liveblogging setup because I don't want to pay for something like CoverItLive. My process is: Local HTML file > Cloud storage (Dropbox/Drive/etc) > iframe on content page. All that works, and with some CSS even looks pretty nice despite the less-than-awesome approach. But here's the thing: the liveblog itself is made up of an HTML table, and I have to manually copy/paste the code for a new row, fill in the timestamp, write the new message, and save the document (which then syncs with the cloud and shows up in the iframe). To simplify the process I've made another HTML file which I intend to run locally and use to add entries to the table automatically. At the moment it's just a bunch of input boxes and some javascript to automate the timestamp and write the table row from the input data.
Code, as it stands now: http://jsfiddle.net/LukeLC/999bH/
What I'm looking to do from here is find a way to somehow export the generated table data to another .html file on my hard drive. So far I've managed to get this code...
if(document.documentElement && document.documentElement.innerHTML){
var a=document.getElementById("tblive").innerHTML;
a=a.replace(/</g,'<');
var w=window.open();
w.document.open();
w.document.write('<pre><tblive>\n'+a+'\n</tblive></pre>');
w.document.close();
}
}
...to open just the generated table code in a new window, and sure, I can save the source from there, but the whole point is to eliminate steps like that from the process.
How can I tell the page to save the generated code to a separate .html file when I click on the 'submit' button? Again, all of this happens locally, not on a server.
I'm not very good with javascript--and maybe a different language will be necessary--but any help is much appreciated.
I suppose you could do something like this:
var myHTMLDoc = "<html><head><title>mydoc</title></head><body>This is a test page</body></html>";
var uri = "data:application/octet-stream;base64,"+btoa(myHTMLDoc);
document.location = uri;
BTW, btoa might not be cross-browser, I think modern browsers all have it, but older versions of IE don't. AFAIK base64 isn't even needed. you might be able to get away with
var uri = "data:application/octet-stream,"+myHTMLDoc;
Drawbacks with this is that you can't set the filename when it gets saved
You cant do this with javascript but you can have a HTML5 link to open save dialogue:
<a href="pageToDownload.html" download>Download</a>
You could add some smarts to automate it on the processed page after the POST.
fiddle : http://jsfiddle.net/ghQ9M/
Simple answer, you can't.
JavaScript is restricted to perform such operations due to security reasons.
The best way to accomplish that, would be, to call a server page that would write
the new file on the server. Then from javascript perform a POST request to the
server page passing the data you want to write to the new file.
If you want the user to save the page to it's file system, this is a different
problem and the best approach to accomplish that, would be to, notify the user/ask him
to save the page, that page could be your new window like you are doing w.open().
Let me do some demonstration for you:
//assuming you know jquery or are willing to use it :)
var html = $("#tblive").html().replace(/</g, '<');
//generating your download button
$.post('generate_page.php', { content: html })
.done(function( data ) {
var filename = data;
//inject some html to allow user to navigate to the new page (example)
$('#tblive').parent().append(
'Check your Dynamic Page!');
// you data here, is the response from the server so you can return
// your new dynamic page file name here.
// and maybe to some window.location="new page";
});
On the server side, something like this:
<?php
if($_REQUEST["content"]){
$pagename = uniqid("page_", true) . '.html';
file_put_contents($pagename, $_REQUEST["content"]);
echo $pagename;
}
?>
Some notes, I haven't tested the example, but it works in theory.
I assume that with this the effort to implement it should be minimal, assuming this solves your problem.
A server based solution:
You'll need to set up a server (or your PC) to serve your HTML page with headers that tell your browser to download the page instead of processing the HTML markup. If you want to do this on your local machine, you can use software such as WAMP (or MAMP for Mac or LAMP for Linux) that is basically a web server in a .exe. It's a lot of hassle but it'll work.

How to download the current page as a file / attachment using Javascript?

I am aware of the hidden iFrame trick as mentioned here (http://stackoverflow.com/questions/365777/starting-file-download-with-javascript) and in other answers.
I am interested in a similar problem:
How can I use Javascript to download the current page (IE: the current DOM, or some sub-set of it) as a file?
I have a web page which fetches results from a non-deterministic query (eg. a random sample) to display to the user. I can already, via a querystring parameter, make the page return a file instead of rendering the page. I can add a "Get file version" button (our standard approach) but the results will be different to those displayed because it is a different run of the query.
Is there any way via Javascript to download the current page as a file, or is copying to the clipboard my only option?
EDIT
An option suggested by Stefan Kendall and dj_segfault is to write the result server side for later retrieval. Good idea, but unfortunately writing files server side is out of the question in this instance.
How about shudder passing the innerHTML as a post parameter to another page?
You can try with the protocol data:text/attachment
Like in:
<html>
<head>
<style>
</style>
</head>
<body>
<div id="hello">
<span>world</span>
</div>
<script>
(function(){
document.location =
'data:text/attachment;,' + //here is the trick
document.getElementById('hello').innerHTML;
//document.documentElement.innerHTML; //To Download Entire Html Source
})();
</script>
</body>
</html>
Edit after shesek comment
To add to Mic's terrific answer above, some additional points:
If you have Unicode content (Or want to preserve indentation in the source), you need to convert the string to Base64 and tell the Data URI to treat the data as such:
(function(){
document.location =
'data:text/attachment;base64,' + // Notice the new "base64" bit!
utf8_to_b64(document.getElementById('hello').innerHTML);
//utf8_to_b64(document.documentElement.innerHTML); //To Download Entire Html Source
})();
function utf8_to_b64( str ) {
return window.btoa(unescape(encodeURIComponent( str )));
}
utf_to_b64() via MDN -- works in Chrome/FF.
You can drop this all into an anchor tag, allowing you to set the download attribute:
<a onclick="$(this).attr('href', 'data:text/plain;base64,' + utf8_to_b64($('html').clone().find('#generate').remove().end()[0].outerHTML));" download="index.html" id="generate">Generate static</a>
This will download the current page's HTML as index.html and removes the link used to generate the output. This assumes the utf8_to_b64() function from above is defined somewhere else.
Some useful links on Data URIs:
MDN article
MSDN article
Depending on the size and if support is needed for ancient browsers, but you can consider creating a dynamic file using data: URIs and link to it. I'be seen several places that do that. To get the brorwser to download rather than display it, play around with the content type you put in the URI and use the new html5 download attribute. (Sorry for any typos, I'm writing from my phone)
I don't think you're going to be able to do it exactly the way you want to. JavaScript can't create a file and download it for security reasons. Nor can it create it on the server for download.
What I would do if I were you is, on the server side, create an output file with the session ID in the name in a temp directory as you create the output for the web page, and have a button on the web page with a link to that file.
You'll probably want a separate process to remove files over a day old or something like that.
Can you not cache the query results, and store it by some key? That way you can reference the same report output forever, or until your file garbage collector comes along. This also implies that you can create static URLs to report outputs, which tends to be nice.

Categories