In my xampp htdocs folder I got two files: An image and a php script. I tried to create a word document with an image. This is the code I used:
$image = 'img.png';
$imageData = base64_encode(file_get_contents($image));
$src = 'data: '. mime_content_type($image).';base64,'.$imageData;
header("Content-type: application/vnd.ms-word");
header("Content-Disposition: attachment;Filename=document_name.doc");
echo "<html>";
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Windows-1252\">";
echo "<body>";
echo "<h1>bla</h1>";
echo "<b>My first document</b>";
echo '<img src="',$src,'">';
echo "</body>";
echo "</html>";
Well actually I don't have Microsoft Word installed on my PC but it should work with Libre Office too. I also tried http://www.viewdocsonline.com but it didn't work. First I tried it with a way too big image and I thought that was causing the problem but it doesn't even work with a small image. The File is just loading all the time but can't be opened. The file size seems to be right - it's 52kb - so the image seems to be in the document.
But what could cause the error? How to find out and how to debug?
Word can't read Html, at least not if you specify the .doc extension.
You should use a Docx generator if you want to work with the latest version of Word (since 2007), or doc if you want to create a document readable from word 2003.
http://www.phpdocx.com/ works great for that (https://phpword.codeplex.com/ too, but isn't well supported)
Alright – with the help of edi9999 and his awesome library I was able to create a docx document with my text variables and my image.
Here is the code I used:
Javascript:
/*** importing all necessary scripts ***/
<script type="text/javascript" src="docxtemplater-master/libs/base64.js"></script>
<script type="text/javascript" src="docxtemplater-master/libs/jszip/jszip.js"></script>
<script type="text/javascript" src="docxtemplater-master/libs/jszip/jszip-load.js"></script>
<script type="text/javascript" src="docxtemplater-master/libs/jszip/jszip-inflate.js"></script>
<script type="text/javascript" src="docxtemplater-master/js/docxgen.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
/*** my JSON object with the variables for setTemplateVars() ***/
<script type="text/javascript">
var JSON = { "articles": [
{ "title": "test-title", "first_name": "Paul", "last_name": "Alan", "phone": "555-nose", "fileName": "abc" },
{ "title": "test-title2", "first_name": "John", "last_name": "Doe", "phone": "555-abcd", "fileName": "bcd" }
]
};
</script>
<script type="text/javascript">
var xhrDoc = new XMLHttpRequest();
xhrDoc.open('GET', 'Example.docx', true);
if (xhrDoc.overrideMimeType) {
xhrDoc.overrideMimeType('text/plain; charset=x-user-defined');
}
xhrDoc.onreadystatechange = function (e) {
if (this.readyState == 4 && this.status == 200) {
window.docData = this.response;
}
};
xhrDoc.send();
var xhrImage = new XMLHttpRequest();
xhrImage.open('GET', 'dog.jpg', true);
if (xhrImage.overrideMimeType) {
xhrImage.overrideMimeType('text/plain; charset=x-user-defined');
}
xhrImage.onreadystatechange = function (e) {
if (this.readyState == 4 && this.status == 200) {
window.imgData = this.response;
}
};
xhrImage.send();
generateDoc = function (docData) {
var doc = new DocxGen(docData)
doc.setTemplateVars(
{ "first_name": JSON.articles[0]["first_name"],
"last_name": JSON.articles[0]["last_name"],
"phone": JSON.articles[0]["phone"],
"fileName": JSON.articles[0]["fileName"]
}
)
doc.applyTemplateVars()
imageList = doc.getImageList()
console.log(imageList);
doc.setImage(imageList[0].path, imgData);
doc.output()
}
</script>
HTML:
<button class="download_doc" onClick="generateDoc(window.docData)">download word docx with image</button>
Word template:
{phone}
Product name: {first_name}
Product reference : {last_name}
*in the middle is an image*
Blabla: {fileName}
*here is another image*
Well the content makes no sense of course but it works. But still there are some questions left (especially to edi9999 and I hope you could answer them for me please :) ):
1. The images has to be on the same server and you have to use a relative path, right? Link's didn't seem to work. I tried xhrImage.open('GET', 'http://link-to-an-image.com/image.jpg', true); but without success. Is it somehow possible to use external links to images?
2. There is an 304 error ("Not modified") in the console behind the GET Requests. Is that normal?
3. Does the image that shall replace the image in the word document have to be the same size (or at least the same aspect ratio) or are there any option variables that could make the replacement more flexible? For example: if I wanna have the image displayed over the full width in the word document and got a replacement image with a different aspect ratio, would it be possible to keep that aspect ratio and just increase the height of the image in the word document?
4. How to use more than one image for replacement? With xhrImage.open('GET', 'dog.jpg', true); only one image is opened. How to add more images to the "imageList" and how to determine the order?
5. The library is based on prototype and normally it's causing errors to use both (jQuery + Prototype) frameworks in one document. But I tried to use a jQuery function and it worked. Have you ever had any problems with using your library and jQuery in one document?
Found another solution:
With this library: https://github.com/PHPOffice/PHPWord
it's quite easy to create a docx file with formatted text and an image.
Here's the code that worked for me:
require_once('PHPWord-master/Classes/PHPWord.php');
$PHPWord = new PHPWord();
$section = $PHPWord->createSection();
$my_text='Hello world! I am formatted.';
$section->addText($my_text, array('name'=>'Tahoma', 'size'=>16, 'bold'=>true));
$section->addText(''); // adding some white space because the marginTop attribute of the image doesn't work
$filename="Jellyfish.jpg";
$size = getimagesize($filename);
$width="560"; //full width in a word document if image is 96dpi
$height=560/intval($size[0])*intval($size[1]);
$section->addImage(
$filename,
array(
'width' => $width,
'height' => $height,
'align' => 'center'
)
);
$section->addText('blabla');
$filename="dog.jpg";
$size = getimagesize($filename);
$height=560/intval($size[0])*intval($size[1]);
$section->addImage(
$filename,
array(
'width' => $width,
'height' => $height,
'align' => 'center'
)
);
$objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
$objWriter->save('helloWorld.docx');
Related
This is the code in my js
(function(){
var video = document.getElementById('video'),
canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
photo = document.getElementById('photo'),
vendorUrl = window.URL || window.webkitURL;
datas = canvas.toDataURL('images/png');
navigator.getMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
navigator.getMedia({
video: true,
audio: false
}, function(stream){
video.src = vendorUrl.createObjectURL(stream);
video.play();
}, function(error){
});
document.getElementById('capture').addEventListener('click',function(){
context.drawImage(video, 0, 0, 400, 300);
photo.setAttribute('src', canvas.toDataURL('images/png'));
datas = canvas.toDataURL('images/png');
});
var canvasData = canvas.toDataURL("image/png");
var ajax = new XMLHttpRequest();
ajax.open("POST",'webcam.php',false);
ajax.setRequestHeader('Content-Type', 'application/upload');
ajax.send(canvasData);
})();
This is the php code to receive the data
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
echo "true";
// Get the data
$imageData=$GLOBALS['HTTP_RAW_POST_DATA'];
// Remove the headers (data:,) part.
// A real application should use them according to needs such as to check image type
$filteredData=substr($imageData, strpos($imageData, ",")+1);
// Need to decode before saving since the data we received is already base64 encoded
$unencodedData=base64_decode($filteredData);
//echo "unencodedData".$unencodedData;
// Save file. This example uses a hard coded filename for testing,
// but a real application can specify filename in POST variable
$fp = fopen( 'test.png', 'wb' );
fwrite( $fp, $unencodedData);
fclose( $fp );
}
?>
<head>
<meta charset="UTF-8">
<Title>Document</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="booth">
<video id = "video" width="400" height="300"></video>
Snap Shot
<canvas id="canvas" width="400" height="300"></canvas>
<img id ="photo" name = "photo" src="images/events/default.png" alt="Photo of you">
</div>
<script src="js/photo.js"></script>
</body>
<?php
?>
The application intends to take a snapshot of the user and saves the photo via javascript. I am trying to find a way to send the data back to php and utilize it to save into the database. I understand it is saved in base64 encode. I tried different methods of Ajax including the one I have saved, but the data tends to not send any data to the php folder.
Thank you in advanced.
I just suggest you to check some of you code points:
Form content type. To upload files you must use "multipart/form-data"
ajax.setRequestHeader('Content-Type', 'multipart/form-data');
You can use FormData class in JS to make form data before sending:
https://developer.mozilla.org/en/docs/Web/API/FormData/append
Canvas function "toDataURL" have no mime types "images/png". Just "image/png"
I'm using Froalo for text editing, but I'm having difficulties getting the image upload to function correctly. Testing on localhost.
The documentation says that
imageUploadURL: '/upload_image.php',
should return a json string formated like this :
{ link: 'path/to/image.jpg' }
my javascript looks this this :
$(function() {
$('#edit').froalaEditor({
language:'fr',
imageUploadURL: 'upload.php'
})
});
my upload.php looks like this :
var_dump($_FILES);
require('clean.php'); // removes french special characters
$image = clean($_FILES['file']['name']);
$uploaddir = '../photos/';
$uploadfile = $uploaddir . basename($image);
$retour = ['link'=> $uploadfile];
$b = json_encode($retour);
$array_final = preg_replace('/"([a-zA-Z]+[a-zA-Z0-9_]*)":/','$1:',$b);
if( move_uploaded_file($_FILES['file']['tmp_name'],$uploadfile)) {
echo stripslashes($array_final);
} else {
echo "Lo kol kakh tov...";
}
When I run this from the text editor through froalaEditor,
the file gets uploaded to the server,
firebug says that upload.php
answers the array $_FILES and :
{link:"../photos/sama1.jpg"}
That all seems good, but froala answers that "something" went wrong and the images doesn't appear in the editor.
Could it be because of the double quotes around the image url?
Solution was dead simple : the problem was this:
{link:"../photos/sama1.jpg"}
It didn't like the relative path so changing it to either this :
{link:"/var/www/html/blabla/photos/sama1.jpg"}
or this
{link:"/photos/sama1.jpg"}
did the trick :)
I have an angular app that will display some images. I am opening a prettyPhoto ajax window and passing the pathname to the URL. My script is loading the image fine, however, it isn't displaying the image how prettyPhoto traditionally displays a photo.
What do I need to do so it behaves like it is displaying a photo? i.e: has the fullscreen button, resizes the lightbox to the photo etc.
Is that even possible?
I am opening the lightbox via:
$scope.openLightbox = function()
{
if (typeof $.prettyPhoto.open !== "function")
{
$.fn.prettyPhoto({
social_tools:false,
deeplinking: false,
keyboard_shortcuts: false
});
$.prettyPhoto.open('resources/php/view/lightbox.php?ajax=true&path=' + $base64.encode($scope.currentFile));
return;
}
$.prettyPhoto.open('resources/php/view/lightbox.php?ajax=true&path=' + $base64.encode($scope.currentFile));
}
$scope.currentFile would be something like: data/39/my_image_name.jpg
and I am parsing the PHP like so:
$path = base64_decode($_GET['path']);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
$mimeExt = explode('/', $mime);
if ($mimeExt[0] == 'image')
{
echo '<img width="100%" height="100%" src="data:image/' . $mimeExt[1] . ';base64,' . base64_encode(file_get_contents($path)) . '">';
}
elseif ($mimeExt[0] == 'video')
{
}
finfo_close($finfo);
Like I said above, the image is displaying just fine, I just want it to be displayed with the standard prettyPhoto image behavior. I understand this may not be possible.
EDIT
So turns out I didn't need AJAX afterall:
$scope.openLightbox = function()
{
if (typeof $.prettyPhoto.open !== "function")
{
$.fn.prettyPhoto({
social_tools:false,
deeplinking: false,
keyboard_shortcuts: false
});
$.prettyPhoto.open('resources/php/view/lightbox.php?path=' + $base64.encode($scope.currentFile));
return;
}
$.prettyPhoto.open('resources/php/view/lightbox.php?path=' + $base64.encode($scope.currentFile));
}
and finally my php which I am outputting the image directly to the browser so prettyPhoto thinks it is just loading an image
<?php
require("../config.php");
require("../connect.php");
session_start();
if (isset($_SESSION['ds_level']))
{
$path = base64_decode($_GET['path']);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
$mimeExt = explode('/', $mime);
if ($mimeExt[0] == 'image')
{
header('Content-Type: image/' . $mimeExt[1]);
echo file_get_contents($path);
}
elseif ($mimeExt[0] == 'video')
{
//do other stuff to display video
}
finfo_close($finfo);
}
else
{
//-- no access
}
?>
What do I need to do so it behaves like it is displaying a photo? i.e: has the fullscreen button, resizes the lightbox to the photo etc.
Is that even possible?
Yes, it is possible. You need to create a dedicated directive, as specified in this Gist:
.directive('prettyp', function(){
return function(scope, element, attrs) {
$("[rel^='prettyPhoto']").prettyPhoto({deeplinking: false, social_tools: false});
}
})
To apply it, specify rel="prettyPhoto" in the anchor, like so:
<a prettyp ng-href="{{image.url}}" rel="prettyPhoto[main]" target="_blank" title="{{image.title}}">
HOW IT WORKS
The directive looks for a rel attribute starting with prettyPhoto, and applies the prettyPhoto magic to it.
EXAMPLE
I made a Plunk you can play around with: check the Plunk
IN YOUR CODE
To apply the directive in your code, you could replace:
echo '';
with:
echo '<img width="100%" height="100%" src="data:image/' . $mimeExt[1] . ';base64,' . base64_encode(file_get_contents($path)) . '">';
EDIT AFTER CHAT SESSION
As your images are protected with .htaccess, you have opted to work with a base64 version of your image, and why not?
However, it seems that if you wait until the user clicks the 'view' button in your app, it takes too long to go fetch the protected image and encode it, before passing it on to prettyPhoto:
I recommend you go fetch your image before the user clicks the view button, when the user selects the image in the list.
The long process of:
make an ajax call to php server;
have php app fetch image;
have php app encode image;
have angularjs/javaScript app store the base64 string
can then be done automatically, preventively, in the background.
The user experience would then be optimised.
So when the user does click the view button, the base64 version of the image can be passed to prettyPhoto straight away, without any server call: this would produce the same result as displayed in the plunkr I provided, when the button is pressed.
I am looking for a PHP script that will allow me to draw an image with my mouse and save it as an image. If you know of any please help.
In case you do feel like reinventing a few wheels :-)
Make a Javascript snippet that lets you draw. This can of course be as advanced or simple as you wish, for example:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
pos = false;
ctx.strokeStyle = "red";
$(canvas).bind("mousedown", function(evt) {
pos = {x: evt.layerX, y: evt.layerY};
ctx.beginPath();
ctx.moveTo(pos.x, pos.y);
});
$(canvas).bind("mousemove", function(evt) {
if(!pos) return; // You may not want to do this on every mousemove.
pos = {x: evt.layerX, y: evt.layerY};
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
});
$(canvas).bind("mouseup", function(evt) {
if(!pos) return;
ctx.closePath();
pos = false;
});
Also add a button that sends the image data to your PHP script:
$('#btn').bind("click", function(evt) {
$.post('saveImage.php', {image : canvas.toDataURL('image/jpeg')});
});
In your saveImage.php script on the server, decode the data and write it to a file.
$imgData = $_POST["image"]; // Probably a good idea to sanitize the input!
$imgData = str_replace(" ", "+", $imgData);
$imgData = substr($imgData, strpos($imgData, ","));
$file = fopen('myImage.jpg', 'wb');
fwrite($file, base64_decode($imgData));
fclose($file);
Should do the trick :-) I'm using jQuery for the JS bits here, that's of course not necessary.
PHP is executed server-side, whereas interaction with the mouse is carried out client-side. You would need to use an in-browser technology like JavaScript or Flash to capture the mouse movements and generate bitmap data first.
I have a function in javascript called "dumpData" which I call from a button on an html page as **onlick="dumpData(dbControl);"* What it does is return an xml file of the settings (to an alert box right now). I want to return it to the user as a file download. Is there a way to create a button when click will open a file download box and ask the user to save or open it? (sorta of like right-clicking and save target as)...
Or can it be sent to a php file and use export();? Not sure how I would send a long string like that to php and have it simple send it back as a file download.
Dennis
I don't think you can do that with javascipt, at least not with a nice solution.
Here's how to force a download of a file in PHP:
$file = "myfile.xml";
header('Content-Type: application/xml');
header("Content-Disposition: attachment; filename='$file'");
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
Instead of using readfile to output your file, you could also directly display content using echo.
/EDIT: hell, someone was faster :).
EDITED:
just a proof of concept.. but you get the idea!
instead of
<a onlick="dumpData(dbControl); href="#">xml file</a>
you can have like this:
xml file
then like this:
// Assuming your js dumpData(dbControl); is doing the same thing,
// retrieve data from db!
$xml = mysql_query('SELECT * FROM xml WHERE id= $_GET['id'] ');
header("Content-type: text/xml");
echo $xml;
I eneded up going this route:
The HTML code
<script type="text/javascript">
$(document).ready(function() {
$("#save").click(function(e) { openDialog() } );
});
</script>
<button id="save" >Send for processing.</button>
The javascript code:
function openDialog() {
$("#addEditDialog").dialog("destroy");
$("#Name").val('');
$("#addEditDialog").dialog({
modal: true,
width: 600,
zIndex: 3999,
resizable: false,
buttons: {
"Done": function () {
var XMLname = $("#Name").val();
var XML = dumpXMLDocument(XMLname,geomInfo);
var filename = new Date().getTime();
$.get('sendTo.php?' + filename,{'XML':XML}, function() {
addListItem(XMLname, filename + ".XML");
});
$(this).dialog('close');
},
"Cancel": function () {
$("#Name").val('');
$(this).dialog('close');
//var XMLname = null;
}
}
});
}
PHP Code, I just decided to write the file out to a directory. Since I created the filename in the javascript and passed to PHP, I knew where it was and the filename, so I populated a side panel with a link to the file.
<?php
if(count($_GET)>0)
{
$keys = array_keys($_GET);
// first parameter is a timestamp so good enough for filename
$XMLFile = "./data/" . $keys[0] . ".kml";
echo $XMLFile;
$fh = fopen($XMLFile, 'w');
$XML = html_entity_decode($_GET["XML"]);
$XML = str_replace( '\"', '"', $XML );
fwrite($fh, $XML);
fclose($fh);
}
//echo "{'success':true}";
echo "XMLFile: ".$XMLFile;
?>
I don't know why, but when I send the XML to my php file it wrote out the contents withs escape charters on all qoutes and double quotes. So I had to do a str_replace to properly format the xml file. Anyone know why this happens?
POST the XML via a form to a php script that writes it back to the client with a Content-Disposition: attachment; filename=xxx.xml header.
<form name="xml_sender" action="i_return_what_i_was_posted.php" method="POST">
<input type="hidden" name="the_xml" value="" />
</form>
Then with js
function dumpData(arg) {
var parsedXML = ??? //whatever you do to get the xml
//assign it to the the_xml field of the form
document.forms["xml_sender"].the_xml.value = parsedXML;
//send it to the script
document.forms["xml_sender"].submit();
}
Can't remember if this loses the original window, if so, post to an iframe.