Moin Moin!
Mit Javascript ... : Es ist nicht unmöglich, aber sehr schwierig und vor allem sehr umständlich, sich in Javascript innerhalb des Browsers aus nichts eine PDF-Datei zusammenzufummeln.
Gib mal einen Tipp, wie das funktionieren soll?
Javascript ist Turing-vollständig. Also kann man sich aus Eingangsdaten und einigen Konstanten die Bytefolge zusammenrechnen, die eine PDF-Datei mit den Daten repräsentiert. Java, PHP, Perl & Co. treiben serverseitig nichts anderes.
Hat man die Bytefolge berechnet, muß man nur noch den Browser überreden, diese Bytefolge als eigenständiges Dokument anzusehen und anzuzeigen bzw. zum Speichern anzubieten. Über data:-URLs nach RFC 2397 klappt das einigermaßen, wenn man die Bytefolge in ihre Base64-Repräsentation umrechnet.
Beispiel:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
<script type="text/javascript">
function calcpdf()
{
return 'JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFIvRmlsdGVyIC9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nHWOywrCQAxF9/MVWdrFxGTe3QqiuFPHlbjQ+kCwSsH/x2mlMIKTS+CQx006IGQF1GuEphUEi5Q30YmAuo+hkXPTwiyK6cZD2opXQVjXteGhx6CcRQrgHaMJEFuxn+wqSaitUawnz4xPGV8KM8dCPed35YgOcSWkooDWaZCsMBiI53R9WXB7FPg1uim26J0H6bxBq75u28LP959//s9AxjxemUexTvoAfoJQ1WVuZHN0cmVhbQplbmRvYmoKNiAwIG9iagoxNzMKZW5kb2JqCjQgMCBvYmoKPDwvVHlwZS9QYWdlL01lZGlhQm94IFswIDAgNTk1IDg0Ml0KL1JvdGF0ZSAwL1BhcmVudCAzIDAgUgovUmVzb3VyY2VzPDwvUHJvY1NldFsvUERGIC9UZXh0XQovRm9udCA4IDAgUgo+PgovQ29udGVudHMgNSAwIFIKPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFsKNCAwIFIKXSAvQ291bnQgMQovUm90YXRlIDA+PgplbmRvYmoKMSAwIG9iago8PC9UeXBlIC9DYXRhbG9nIC9QYWdlcyAzIDAgUgovTWV0YWRhdGEgOSAwIFIKPj4KZW5kb2JqCjggMCBvYmoKPDwvUjcKNyAwIFI+PgplbmRvYmoKNyAwIG9iago8PC9CYXNlRm9udC9Db3VyaWVyL1R5cGUvRm9udAovU3VidHlwZS9UeXBlMT4+CmVuZG9iago5IDAgb2JqCjw8L1R5cGUvTWV0YWRhdGEKL1N1YnR5cGUvWE1ML0xlbmd0aCAxNDg1Pj5zdHJlYW0KPD94cGFja2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPD9hZG9iZS14YXAtZmlsdGVycyBlc2M9IkNSTEYiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSdhZG9iZTpuczptZXRhLycgeDp4bXB0az0nWE1QIHRvb2xraXQgMi45LjEtMTMsIGZyYW1ld29yayAxLjYnPgo8cmRmOlJERiB4bWxuczpyZGY9J2h0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMnIHhtbG5zOmlYPSdodHRwOi8vbnMuYWRvYmUuY29tL2lYLzEuMC8nPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0nMGNlNTlkNTItNGQ4Ny0xMWUxLTAwMDAtYWQ2MmEyMDgwOTI3JyB4bWxuczpwZGY9J2h0dHA6Ly9ucy5hZG9iZS5jb20vcGRmLzEuMy8nIHBkZjpQcm9kdWNlcj0nR1BMIEdob3N0c2NyaXB0IDguNjMnLz4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9JzBjZTU5ZDUyLTRkODctMTFlMS0wMDAwLWFkNjJhMjA4MDkyNycgeG1sbnM6eGFwPSdodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvJyB4YXA6TW9kaWZ5RGF0ZT0nMjAxMi0wMS0zMFQxMToxNjo0NiswMTowMCcgeGFwOkNyZWF0ZURhdGU9JzIwMTItMDEtMzBUMTE6MTY6NDYrMDE6MDAnPjx4YXA6Q3JlYXRvclRvb2w+XDM3NlwzNzdcMDAwUFwwMDBEXDAwMEZcMDAwQ1wwMDByXDAwMGVcMDAwYVwwMDB0XDAwMG9cMDAwclwwMDAgXDAwMFZcMDAwZVwwMDByXDAwMHNcMDAwaVwwMDBvXDAwMG5cMDAwIFwwMDAwXDAwMC5cMDAwOVwwMDAuXDAwMDc8L3hhcDpDcmVhdG9yVG9vbD48L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9JzBjZTU5ZDUyLTRkODctMTFlMS0wMDAwLWFkNjJhMjA4MDkyNycgeG1sbnM6eGFwTU09J2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8nIHhhcE1NOkRvY3VtZW50SUQ9JzBjZTU5ZDUyLTRkODctMTFlMS0wMDAwLWFkNjJhMjA4MDkyNycvPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0nMGNlNTlkNTItNGQ4Ny0xMWUxLTAwMDAtYWQ2MmEyMDgwOTI3JyB4bWxuczpkYz0naHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8nIGRjOmZvcm1hdD0nYXBwbGljYXRpb24vcGRmJz48ZGM6dGl0bGU+PHJkZjpBbHQ+PHJkZjpsaSB4bWw6bGFuZz0neC1kZWZhdWx0Jz5cMzc2XDM3N1wwMDBIXDAwMGFcMDAwbFwwMDBsXDAwMG88L3JkZjpsaT48L3JkZjpBbHQ+PC9kYzp0aXRsZT48ZGM6Y3JlYXRvcj48cmRmOlNlcT48cmRmOmxpPigpPC9yZGY6bGk+PC9yZGY6U2VxPjwvZGM6Y3JlYXRvcj48L3JkZjpEZXNjcmlwdGlvbj4KPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSd3Jz8+CmVuZHN0cmVhbQplbmRvYmoKMiAwIG9iago8PC9Qcm9kdWNlcihHUEwgR2hvc3RzY3JpcHQgOC42MykKL0NyZWF0aW9uRGF0ZShEOjIwMTIwMTMwMTExNjQ2KzAxJzAwJykKL01vZERhdGUoRDoyMDEyMDEzMDExMTY0NiswMScwMCcpCi9UaXRsZShcMzc2XDM3N1wwMDBIXDAwMGFcMDAwbFwwMDBsXDAwMG8pCi9DcmVhdG9yKFwzNzZcMzc3XDAwMFBcMDAwRFwwMDBGXDAwMENcMDAwclwwMDBlXDAwMGFcMDAwdFwwMDBvXDAwMHJcMDAwIFwwMDBWXDAwMGVcMDAwclwwMDBzXDAwMGlcMDAwb1wwMDBuXDAwMCBcMDAwMFwwMDAuXDAwMDlcMDAwLlwwMDA3KQovQXV0aG9yKCkKL0tleXdvcmRzKCkKL1N1YmplY3QoKT4+ZW5kb2JqCnhyZWYKMCAxMAowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDA0ODYgMDAwMDAgbiAKMDAwMDAwMjIwMiAwMDAwMCBuIAowMDAwMDAwNDE4IDAwMDAwIG4gCjAwMDAwMDAyNzcgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwMjU4IDAwMDAwIG4gCjAwMDAwMDA1NzkgMDAwMDAgbiAKMDAwMDAwMDU1MCAwMDAwMCBuIAowMDAwMDAwNjQxIDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUgMTAgL1Jvb3QgMSAwIFIgL0luZm8gMiAwIFIKL0lEIFs8Q0QyRTI4MTc4QTdBOURBNjlGNzIwNjAxOTQyRTI5OEY+PENEMkUyODE3OEE3QTlEQTY5RjcyMDYwMTk0MkUyOThGPl0KPj4Kc3RhcnR4cmVmCjI1MzkKJSVFT0YK';
}
function genpdf(e)
{
var ifr=document.createElement("iframe");
ifr.src="data:application/pdf;base64,"+calcpdf();
e.parentNode.appendChild(ifr);
return true;
}
</script>
</head>
<body>
<button onclick="genpdf(this)">PDF erzeugen</button>
</body>
</html>
Das PDF wird in diesem Beispiel allerdings nicht in JS berechnet, sondern ist schon vorberechnet und in Base64 umgewandelt. Die Funktion calcpdf() müßte gegen eine ausgetauscht werden, die vorhandene Daten wie oben beschrieben umrechnet und als Base64-String zurückgibt.
Probleme macht wie üblich der IE, der bis Version 7 mit data:-URLs gar nichts anfangen kann und in Version 8 die URL-Länge auf 32 KBytes begrenzt.
Alexander
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".