By: Olivier
Date: 2007-06-06
Time: 12:20
|
Re: Génération de document pdf
Bonjour,
Voici quelques informations pour l'installation d'OpenOffice sous Linux sans X (tests effectués sur une Fedora).
Le code date de 2 ans et c'etait OpenOffice 1.1
J'ai fais une petite compilation de la procedure pour l'installer.
*** Votre mission sera de la faire refonctionner et de la partager aux autres ***
Pour information je suis parti de l'exemple de OOconvert
http://delta-flyer.musc.edu/ooconvert/
Mais je n'ai ni besoin du Perl, ni besoin du Java.
PHP fait une requete au service de conversion
Ce service de conversion est lancé via OpenOffice et le script Python associé
1/---> Installation de XVFB
Xorg doit être installé.
Vérifier que xvfb est installé avec « up2date -i xorg-x11-Xvfb»
Télécharger xvfb-run (--nodeps) à partir de http://distro.ibiblio.org/pub/linux/distributions/altlinux/Sisyphus/noarch/RPMS.master/xvfb-run-1.2-alt1.noarch.rpm
Les dépendances requises sont résolues mais les noms de packages ne sont pas les même. Installer avec –nodeps.
2/---> Installation d’Open Office
up2date -i openoffice.org (ATTENTION, plutot utiliser yum)
Telecharger si besoin le package openoffice.org-pyuno-2.0.1-1.i586.rpm pour supporter le langage python dans OpenOffice
3/---> Creation d'un utilisateur, par exemple oobatch
groupadd –g 5000 oobatch
useradd –c "Utilisateur Batch conversion OOCONVERT" –d /home/oobatch –g 5000 –m –s /bin/bash –u 5000 oobatch
cd /home/oobatch/
faire ls –al /home/oobatch et vérifier la presence de fichier .openoffice* (Si OpenOffice a déjà été lancé avec le user oobatch)
4/---> Installation du service de conversion
A la fin de /etc/rc.local, ajouter /usr/local/bin/ooconvert.daemon.sh.
Contenu du fichier /usr/local/bin/ooconvert.daemon.sh
#!/bin/bash
su - oobatch -c 'nohup xvfb-run --server-args=":99 -fbdir /tmp" /usr/lib/ooo-1.1/program/soffice "-accept=socket,host=localhost,port=2002;urp;">/dev/null &'
|
Faire chmod 755 /usr/local/bin/ooconvert.daemon.sh
Lancer le script /usr/local/bin/ooconvert.daemon.sh
Faire ps –ax. La sortie devrait contenir quelque chose de ce genre
4757 pts/0 S 0:00 /bin/sh /usr/bin/xvfb-run --server-args=:99 -fbdir /tmp /usr/local/openoffice/program/soffice -acc
4764 pts/0 S 0:00 Xvfb :99 :99 -fbdir /tmp -nolisten tcp
4767 pts/0 S 0:03 /usr/local/openoffice/program/soffice.bin -accept=socket,host=localhost,port=2002;urp;
5/---> Installation des scripts Python
Mettez les 2 fichiers en Python qq part sur votre serveur, dans l'arborescence web par exemple
Creer un repertoire "python"
Mettre les 2 fichiers convooo_calc.py et convooo_writer.py
Attention ils devront être executable par le user php (apache en general). A verifier pour l'utilisateur oobatch
NOTE : attention a ne pas modifier les tabulations et espaces des fichiers Python, car cela en modifie l'interprétation.
Ce n'est pas comme le PHP ou l'on peut justifier comme l'on veut et le début et la fin des instructions sont données en général par les accolades { }
Si vous avez un probleme, je pourrais vous envoyer les fichiers directement, ou je demanderais à Skrol de les mettre sur le site.
contenu du fichier : convooo_calc.py
#!/usr/local/openoffice/program/python
import getopt,sys
import uno
from unohelper import Base,systemPathToFileUrl, absolutize
from os import getcwd
from com.sun.star.beans import PropertyValue
from com.sun.star.beans.PropertyState import DIRECT_VALUE
from com.sun.star.uno import Exception as UnoException
from com.sun.star.io import IOException,XInputStream, XOutputStream
class OutputStream( Base, XOutputStream ):
def __init__( self ):
self.closed = 0
def closeOutput(self):
self.closed = 1
def writeBytes( self, seq ):
sys.stdout.write( seq.value )
def flush( self ):
pass
def main():
retVal = 0
doc = None
try:
opts, args = getopt.getopt(sys.argv[1:], "hc:",["help", "connection-string=" , "csv", "dbf", "dif", "html", "pdf", "excel", "ps", "sylk"])
format = None
url = "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext"
filterName = "Text (Encoded)"
for o, a in opts:
if o in ("-h", "--help"):
usage()
sys.exit()
if o in ("-c", "--connection-string" ):
url = "uno:" + a + ";urp;StarOffice.ComponentContext"
if o == "--cvs":
filterName = "Text - txt - csv (StarCalc)"
if o == "--dbf":
filterName = "dBase"
if o == "--dif":
filterName = "DIF"
if o == "--html":
filterName = "HTML (CalcWriter)"
if o == "--pdf":
filterName = "calc_pdf_Export"
if o == "--excel":
filterName = "MS Excel 97"
if o == "--ps":
filterName = "calc_ps_Export"
if o == "--sylk":
filterName = "SYLK"
#print filterName
if not len( args ):
usage()
sys.exit()
ctxLocal = uno.getComponentContext()
smgrLocal = ctxLocal.ServiceManager
resolver = smgrLocal.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", ctxLocal )
ctx = resolver.resolve( url )
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx )
cwd = systemPathToFileUrl( getcwd() )
outProps = (
PropertyValue( "FilterName" , 0, filterName , 0 ),
PropertyValue( "OutputStream",0, OutputStream(),0))
inProps = PropertyValue( "Hidden" , 0 , True, 0 ),
for path in args:
try:
fileUrl = uno.absolutize( cwd, systemPathToFileUrl(path) )
doc = desktop.loadComponentFromURL( fileUrl , "_blank", 0,inProps)
if not doc:
raise UnoException( "Couldn't open stream for unknown reason", None )
doc.storeToURL("private:stream",outProps)
except IOException, e:
sys.stderr.write( "Error during conversion: " + e.Message + "\n" )
retVal = 1
except UnoException, e:
sys.stderr.write( "Error ("+repr(e.__class__)+") during conversion:" + e.Message + "\n" )
retVal = 1
if doc:
doc.dispose()
except UnoException, e:
sys.stderr.write( "Error ("+repr(e.__class__)+") :" + e.Message + "\n" )
retVal = 1
except getopt.GetoptError,e:
sys.stderr.write( str(e) + "\n" )
usage()
retVal = 1
sys.exit(retVal)
def usage():
sys.stderr.write( "usage: ooextract.py --help |\n"+
" [-c <connection-string> | --connection-string=<connection-string>\n"+
" file1 file2 ...\n"+
"\n" +
"Extracts plain text from documents and prints it to stdout.\n" +
"Requires an OpenOffice.org instance to be running. The script and the\n"+
"running OpenOffice.org instance must be able to access the file with\n"+
"by the same system path.\n"
"\n"+
"-c <connection-string> | --connection-string=<connection-string>\n" +
" The connection-string part of a uno url to where the\n" +
" the script should connect to in order to do the conversion.\n" +
" The strings defaults to socket,host=localhost,port=2002\n"
"--html \n"
" Instead of the text filter, the writer html filter is used\n"
)
main()
|
contenu du fichier : convooo_writer.py
#!/usr/local/openoffice/program/python
import getopt,sys
import uno
from unohelper import Base,systemPathToFileUrl, absolutize
from os import getcwd
from com.sun.star.beans import PropertyValue
from com.sun.star.beans.PropertyState import DIRECT_VALUE
from com.sun.star.uno import Exception as UnoException
from com.sun.star.io import IOException,XInputStream, XOutputStream
class OutputStream( Base, XOutputStream ):
def __init__( self ):
self.closed = 0
def closeOutput(self):
self.closed = 1
def writeBytes( self, seq ):
sys.stdout.write( seq.value )
def flush( self ):
pass
def main():
retVal = 0
doc = None
try:
opts, args = getopt.getopt(sys.argv[1:], "hc:",["help", "connection-string=" , "html", "pdf", "rtf", "text", "word"])
format = None
url = "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext"
filterName = "Text (Encoded)"
for o, a in opts:
if o in ("-h", "--help"):
usage()
sys.exit()
if o in ("-c", "--connection-string" ):
url = "uno:" + a + ";urp;StarOffice.ComponentContext"
if o == "--html":
filterName = "HTML (StarWriter)"
if o == "--pdf":
filterName = "writer_pdf_Export"
if o == "--rtf":
filterName = "Rich Text Format"
if o == "--text":
filterName = "Text"
if o == "--word":
filterName = "MS Word 97"
#print filterName
if not len( args ):
usage()
sys.exit()
ctxLocal = uno.getComponentContext()
smgrLocal = ctxLocal.ServiceManager
resolver = smgrLocal.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", ctxLocal )
ctx = resolver.resolve( url )
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx )
cwd = systemPathToFileUrl( getcwd() )
outProps = (
PropertyValue( "FilterName" , 0, filterName , 0 ),
PropertyValue( "OutputStream", 0, OutputStream(),0))
inProps = PropertyValue( "Hidden" , 0 , True, 0 ),
for path in args:
try:
fileUrl = uno.absolutize( cwd, systemPathToFileUrl(path) )
doc = desktop.loadComponentFromURL( fileUrl , "_blank", 0,inProps)
if not doc:
raise UnoException( "Couldn't open stream for unknown reason", None )
doc.storeToURL("private:stream",outProps)
except IOException, e:
sys.stderr.write( "Error during conversion: " + e.Message + "\n" )
retVal = 1
except UnoException, e:
sys.stderr.write( "Error ("+repr(e.__class__)+") during conversion:" + e.Message + "\n" )
retVal = 1
if doc:
doc.dispose()
except UnoException, e:
sys.stderr.write( "Error ("+repr(e.__class__)+") :" + e.Message + "\n" )
retVal = 1
except getopt.GetoptError,e:
sys.stderr.write( str(e) + "\n" )
usage()
retVal = 1
sys.exit(retVal)
def usage():
sys.stderr.write( "usage: ooextract.py --help |\n"+
" [-c <connection-string> | --connection-string=<connection-string>\n"+
" file1 file2 ...\n"+
"\n" +
"Extracts plain text from documents and prints it to stdout.\n" +
"Requires an OpenOffice.org instance to be running. The script and the\n"+
"running OpenOffice.org instance must be able to access the file with\n"+
"by the same system path.\n"
"\n"+
"-c <connection-string> | --connection-string=<connection-string>\n" +
" The connection-string part of a uno url to where the\n" +
" the script should connect to in order to do the conversion.\n" +
" The strings defaults to socket,host=localhost,port=2002\n"
"--html \n"
" Instead of the text filter, the writer html filter is used\n"
"--pdf \n"
" Instead of the text filter, the writer pdf filter is used\n"
)
main()
|
6/---> Installation de la bibliothèque PHP
Mettez le fichier ci-dessous avec vos bibliothèques
contenu de : convooo_class.php
<?php
/*
********************************************************
ConvOOo
********************************************************
Author : Olivier LOYNET (tbsooo@free.fr)
Version : 0.1.5
Require : PHP >= 4.0.6
Date : 2005-09-24
Web site : www.tinybutstrong.com
********************************************************
Released under the GNU GPL license
http://www.gnu.org/copyleft/gpl.html
********************************************************
Inspired and enhanced from :
http://delta-flyer.musc.edu/ooconvert/
Don't have to use the Perl scripts in /cgi-bin
********************************************************
*/
class clsConvOOo
{
// ===== public properties =====
var $source_filename = '';
var $target_type = '';
var $target_filename = '';
var $error_message = '';
// ===== private properties =====
var $_python_bin = '';
var $_python_script_dir = '';
var $_python_script_calc = 'convooo_calc.py';
var $_python_script_writer = 'convooo_writer.py';
// ===== constructor =====
function clsConvOOo()
{
}
// ===== public method =====
function SetPythonBin($binary)
{
// set the binary for 'Python scripts'
if ($binary == '') {
$this->error_message = 'Python binary not set';
return false;
}
$this->_python_bin = $this->_BinaryQuote($binary);
return true;
}
function SetPythonScriptDir($path)
{
// set the path Python script directory
$this->_python_script_dir = $path.($path != '' && substr($path, -1, 1) != '/' ? '/' : '');
}
function SetPythonScriptCalc($script)
{
// set the Python script calc
if ($script == '') {
$this->error_message = 'Python script to convert calc is not set';
return false;
}
if (!file_exists($this->_python_script_dir.$script)) {
$this->error_message = 'Python script \''.$script.'\' not found in dir \''.$this->_python_script_dir.'\'';
return false;
}
if (!is_executable($this->_python_script_dir.$script)) {
$this->error_message = 'Python script \''.$script.'\' can\'t be executed';
return false;
}
$this->_python_script_calc = $script;
return true;
}
function SetPythonScriptWriter($script)
{
// set the Python script writer
if ($script == '') {
$this->error_message = 'Python script to convert writer is not set';
return false;
}
if (!file_exists($this->_python_script_dir.$script)) {
$this->error_message = 'Python script \''.$script.'\' not found in dir \''.$this->_python_script_dir.'\'';
return false;
}
if (!is_executable($this->_python_script_dir.$script)) {
$this->error_message = 'Python script \''.$script.'\' can\'t be executed';
return false;
}
$this->_python_script_writer = $script;
return true;
}
function Convert($source_filename, $target_type)
{
$this->source_filename = $source_filename;
$this->target_type = strtolower($target_type);
$this->target_filename = '';
$shell_command = $this->_GetPythonShellCommand();
if ($shell_command === false) {
return false;
} else {
// execute shell command
return shell_exec($shell_command);
}
}
function ConvertToFile($source_filename, $target_type, $target_filename = '')
{
$this->source_filename = $source_filename;
$this->target_type = strtolower($target_type);
$this->target_filename = ($target_filename == '' ? $this->source_filename.'.'.$this->target_type : $target_filename);
$shell_command = $this->_GetPythonShellCommand();
if ($shell_command === false) {
return false;
} else {
exec($shell_command);
// return target filename
return $this->target_filename;
}
}
function RemoveDoc()
{
if ($this->target_filename != '' && file_exists($this->target_filename)) {
unlink ($this->target_filename);
}
}
// ===== private method =====
function _GetPythonShellCommand()
{
// define the python script depends on the OOo document type
$script_name = array();
$script_name['sxc'] = $this->_python_script_calc;
$script_name['stc'] = $this->_python_script_calc;
$script_name['sdc'] = $this->_python_script_calc;
$script_name['ods'] = $this->_python_script_calc; // OpenDocument Spreadsheet
$script_name['ots'] = $this->_python_script_calc; // OpenDocument Spreadsheet Template
$script_name['sxw'] = $this->_python_script_writer;
$script_name['stw'] = $this->_python_script_writer;
$script_name['sdw'] = $this->_python_script_writer;
$script_name['odt'] = $this->_python_script_writer; // OpenDocument Text
$script_name['ott'] = $this->_python_script_writer; // OpenDocument Text Template
// define the convert parameter depend on the OOo document type and the python script
$convert_type = array();
$convert_type[$this->_python_script_calc]['csv'] = '--csv';
$convert_type[$this->_python_script_calc]['dbf'] = '--dbase';
$convert_type[$this->_python_script_calc]['dif'] = '--dif';
$convert_type[$this->_python_script_calc]['htm'] = '--html';
$convert_type[$this->_python_script_calc]['pdf'] = '--pdf';
$convert_type[$this->_python_script_calc]['xls'] = '--excel';
$convert_type[$this->_python_script_calc]['slk'] = '--sylk';
$convert_type[$this->_python_script_writer]['pdf'] = '--pdf';
$convert_type[$this->_python_script_writer]['htm'] = '--html';
$convert_type[$this->_python_script_writer]['txt'] = '--text';
$convert_type[$this->_python_script_writer]['rtf'] = '--rtf';
$convert_type[$this->_python_script_writer]['doc'] = '--word';
// test if Python binary is set
if ($this->_python_bin == '') {
$this->error_message = 'Python binary not fixed';
return false;
}
// test if Python binary exists
if (!file_exists($this->_python_bin)) {
$this->error_message = 'Python binary not exists';
return false;
}
// test if source filename exists
if (!file_exists($this->source_filename)) {
$this->error_message = 'OpenOffice file not exists : \''.$this->source_filename.'\'';
return false;
}
// get the document extension
$source_extension = '';
$a_pathinfo = pathinfo($this->source_filename);
$source_extension = strtolower($a_pathinfo['extension']);
// test if the OOo document can be convert
if (!isset($script_name[$source_extension])) {
$this->error_message = 'can convert only OpenOffice files with extension : sxc, stc, sdc, ods, ots, sxw, stw, sdw, odt, ott';
return false;
}
// test if the Python script exists
if (!file_exists($this->_python_script_dir.$script_name[$source_extension])) {
$this->error_message = 'Python script file not exists';
return false;
}
// test if the source document could be convert by the python script to the target type
if (!isset($convert_type[$script_name[$source_extension]][$this->target_type])) {
$this->error_message = 'target type : \''.$this->target_type.'\' not exists in Python script \''.$script_name[$source_extension].'\'';
return false;
}
// test if target directory exist or is writable
if ($this->target_filename != '') {
if (!is_dir(dirname($this->target_filename))) {
$this->error_message = 'target directory not found : \''.dirname($this->target_filename).'\'';
return false;
}
if (!is_writable(dirname($this->target_filename))) {
$this->error_message = 'target directory not writable : \''.dirname($this->target_filename).'\'';
return false;
}
if (file_exists($this->target_filename)) {
$this->error_message = 'target filename already exist : \''.$this->target_filename.'\'';
return false;
}
}
// generate shell command
$command = $this->_python_bin;
$command.= ' '.$this->_python_script_dir.$script_name[$source_extension];
$command.= ' '.$convert_type[$script_name[$source_extension]][$this->target_type];
$command.= ' '.$this->source_filename;
$command.= ($this->target_filename != '' ? ' > '.$this->target_filename : '');
return $command;
}
function _BinaryQuote($binary)
{
if (strpos($binary, ' ') !== false) {
$binary = (strpos($binary, '"') === 0 ? '' : '"').$binary;
$binary = $binary.((strrpos($binary, '"') == strlen($binary)-1) ? '' : '"');
}
return $binary;
}
}
?>
|
7/---> Exemple d'utilisation en PHP pour la conversion du fichier OpenOffice en PDF ou autre
define('BIN_ZIP' , 'zip');
define('BIN_UNZIP' , 'unzip');
define('BIN_OOO' , '/opt/soffice/program/soffice');
define('BIN_PYTHON' , '/usr/lib/ooo-1.1/program/python');
define('SCRIPT_PYTHON', 'python');
include_once('./inc/convooo_class.php');
$conv = new clsConvOOo();
$conv->SetPythonBin(BIN_PYTHON);
$conv->SetPythonScriptDir(SCRIPT_PYTHON);
$new_filename = $conv->ConvertToFile('fichier_openoffice.sxw', 'pdf');
|
Et voila le travail, pas si simple mais cela fonctionne sans probleme sur un serveur depuis 2 ans
Olivier
|