2012年4月24日 星期二

使用 JODConverter 將 Microsoft Office 文件轉換成 PDF

使用版本:
JODConverter v2.2.2,
LibreOffice v3.5
JODConverter 需要在本機電腦中安裝 LibreOffice (OpenOffice 也可),本處以 LibreOffice 為範例


可轉換類型:
*.doc,
*.ppt,
*.xls,
*.docx,
*.pptx,
*.xlsx


使用教學:

Step1: 安裝 LibreOffice

Step2: 啟動 LibreOffice Service
   1. cd C:\Program Files\LibreOffice 3.5\program
   2. soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard

Step3: 將 JODConverter library 裡的 jar 檔放進專案

完成以上動作後,即可開始測試下面範例程式

使用方式,可傳入檔案完整路徑,或檔案的 File 物件,如

OfficePDFUtil officePDFUtil = new OfficePDFUtil();
officePDFUtil.convert("test.doc""doc.pdf");


<<範例程式>>

import java.io.File;
import java.net.ConnectException;

import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;


public class OfficePDFUtil {

    /**
     * Convert office document to PDF
     *
     * @param inputFile - File path of original office document (*.doc, *.xls, *.ppt)
     * @param outputFile - File path of target pdf document
     * @throws ConnectException
     */
    public void convert(String inputFilePath, String outputFilePath) throws Exception {
        File inputFile = new File(inputFilePath);
        File outputFile = new File(outputFilePath);
        this.convert(inputFile, outputFile);
    }
   
    /**
     * Convert office document to PDF
     *
     * @param inputFile - File of original office document (*.doc, *.xls, *.ppt)
     * @param outputFile - File of target pdf document
     * @throws ConnectException
     */
    public void convert(File inputFile, File outputFile) throws Exception {
      //connect to an OpenOffice.org instance running on port 8100
        OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);

        try {
            connection.connect();

            // convert
            DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
            converter.convert(inputFile, outputFile);
        } catch (Exception e) {
            throw e;
        } finally {
            //close the connection
            try {
                if (connection != null) {
                    connection.disconnect();
                    connection = null;
                }
            } catch (Exception e) {
                throw e;
            }
        }
    }
}

利用 Java 套件 iText 在 PDF 中加入 Watermark




iText 套件下載位址:
http://sourceforge.net/projects/itext/files/

<< 範例程式 >>

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class PdfWatermarkUtil {

    /**
     * Add text water mark
     *
     * @param inputStream - Input file path of the original pdf file.
     * @param outputStream - Output file path of the target pdf file that water
     *            mark is added.
     * @param watermark - Text of water mark.
     * @throws DocumentException
     * @throws IOException
     */
    public void addITextWatermark(String inputFilePath, String outputFilePath, String watermark) throws Exception {
        FileInputStream inputStream = new FileInputStream(inputFilePath);
        FileOutputStream outputStream = new FileOutputStream(outputFilePath);

        this.addITextWatermark(inputStream, outputStream, watermark);
    }

    /**
     * Add text water mark
     *
     * @param inputStream - InputStream of the original pdf file.
     * @param outputStream - OutputStream of the target pdf file that water mark
     *            is added.
     * @param watermark - Text of water mark.
     * @throws DocumentException
     * @throws IOException
     */
    public void addITextWatermark(InputStream inputStream, OutputStream outputStream, String watermark)
            throws Exception {
        Document document = new Document(PageSize.A4);
       
        //Read the existing PDF document
        PdfReader pdfReader = new PdfReader(inputStream);

        //Get the PdfStamper object
        PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream);

        //Get the PdfContentByte type by pdfStamper.
        for (int i = 1, pdfPageSize = pdfReader.getNumberOfPages() + 1; i < pdfPageSize; i++) {
            PdfContentByte pageContent = pdfStamper.getOverContent(i);
            pageContent.setGState(this.getPdfGState());
            pageContent.beginText();
            pageContent.setFontAndSize(this.getBaseFont(), 20);
            pageContent.setColorFill(BaseColor.LIGHT_GRAY);
            pageContent.showTextAligned(Element.ALIGN_CENTER, watermark, document.getPageSize().getWidth() / 2,
                    document.getPageSize().getHeight() / 2, 0);
            pageContent.endText();
        }
        pdfStamper.close();
    }

    /**
     * Get BaseFont
     *
     * @return
     * @throws Exception
     */
    private BaseFont getBaseFont() throws Exception {
        return BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
    }

    /**
     * Get PdfGState
     *
     * @return
     */
    private PdfGState getPdfGState() {
        PdfGState graphicState = new PdfGState();
        graphicState.setFillOpacity(0.7f);
        graphicState.setStrokeOpacity(1f);

        return graphicState;
    }
}

<<注意事項>>
PdfContentByte pageContent = pdfStamper.getOverContent(i);
代表變數 pageContent 所加入的浮水印會在 PDF 內容最上層

若改變為 PdfContentByte pageContent = pdfStamper.getUnderContent(i);
則代表變數 pageContent 所加入的浮水印會在 PDF 內容最下層

此差別在於,當我們針對由 Power Point (*.ppt) 轉出來的 PDF 加浮水印時,若使用 pdfStamper.getUnderContent(i) 會導致加入的浮水印被內容蓋掉而看不到浮水印,因此要改用 pdfStamper.getOverContent(i)。

然而,對於*.doc 及*.xls 目前樣本數不夠多,尚未發現這樣的問題。



Oracle SQL 數子左邊位數不足補 0

函式解說:

LPAD(X,Y[,Z])

把X的左邊加入字元Z(預設的字元是空格),令它的長度成為Y。


範例:把1左邊不足5位數之部份補上0

select LPAD('1',5,'0') from dual;


結果為 00001



2012年4月20日 星期五

RedHat Linux 上安裝 RPM 版本 LibreOffice 3.5


1. 解壓縮
tar zxvf [安裝檔名]
例如:
tar zxvf LibO_3.5.2_Linux_x86-64_install-rpm_en-US.tar.gz

2. 解壓縮的目錄會位於壓縮檔的相同路徑下
例如:
LibO_3.5.2_Linux_x86-64_install-rpm_en-US.tar.gz ← /user/home
LibO_3.5.2rc2_Linux_x86-64_install-rpm_en-US ← 也會在 /user/home

進入解完壓縮後的目錄
cd LibO_3.5.2rc2_Linux_x86-64_install-rpm_en-US/RPMS

並執行下列命令 (必須為 root 帳號)
rpm -Uvh *.rpm

3. 安裝完畢後的路徑
/opt/libreoffice3.5/program


4. 啟動 Service 指令(背景執行)
/usr/bin/nohup /opt/libreoffice3.5/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard 0</dev/null 1>/dev/null 2>/dev/null &



5. shell 檔案如下 (在 server 上啟動 Libre Office 的服務)

<startup_soffice.sh>
#!/bin/bash
# Update source files from Subversion and build them
#
# History
# 2012.04.20 GUC-Kaohung
# create this file

LibreOffice_HOME=/opt/libreoffice3.5/program/soffice.bin

# find tomcat PID
tomcatpid=`ps -ef | grep "$LibreOffice_HOME" | grep -v grep | awk '{print $2}'`
if [ -n "$tomcatpid" ]; then
kill -9 $tomcatpid
echo "LibreOffice3.5 service is stopped."
fi

/usr/bin/nohup /opt/libreoffice3.5/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard 0</dev/null 1>/dev/null 2>/dev/null &
echo "LibreOffice3.5 service is started."

<shutdown_soffice.sh>
#!/bin/bash
# Update source files from Subversion and build them
#
# History
# 2012.04.20 GUC-Kaohung
# create this file

LibreOffice_HOME=/opt/libreoffice3.5/program/soffice.bin

# find tomcat PID
tomcatpid=`ps -ef | grep "$LibreOffice_HOME" | grep -v grep | awk '{print $2}'`
if [ -n "$tomcatpid" ]; then
kill -9 $tomcatpid
echo "LibreOffice3.5 service is stopped."
fi

2012年3月11日 星期日

JSP 生命週期

xxxx.jsp
     ↓
xxxx_jsp.java
     ↓
xxxx_jsp.class
     ↓
載入容器
     ↓
實例化
     ↓
_jspInit()
     ↓
_jspService()
     ↓
_jspDestory()


(以下圖截自 http://web.math.isu.edu.tw/yeh/2010Spring/java/week13/CH08%20%E4%BD%BF%E7%94%A8JSP.pdf )








2011年11月9日 星期三

WSDL2Java 用法


1. 首先必須先下載地三方套件axis.zip,可到下面網址載
   http://www.giveawayoftheday.com/download+axis.zip/
   將 axis.zip 解壓縮至個人電腦中的某一位置 (如 C:\)
   解壓縮後在 C:\ 會出現一個 axis 目錄


2. 新增環境變數 (我的電腦按右鍵 --> 內容 --> 進階 --> 環境變數)
   a.
   AXIS_HOME=C:\axis  (即剛才解壓縮之目錄)

   b.
   AXIS_CLASSPATH=%AXIS_HOME%\WEB-INF\classes;%AXIS_HOME%\WEB-INF\lib\axis.jar;%AXIS_HOME%\WEB-INF\lib\axis-ant.jar;%AXIS_HOME%\WEB-INF\lib\commons-discovery-0.2.jar;%AXIS_HOME%\WEB-INF\lib\commons-logging-1.0.4.jar;%AXIS_HOME%\WEB-INF\lib\jaxrpc.jar;%AXIS_HOME%\WEB-INF\lib\log4j-1.2.8.jar;%AXIS_HOME%\WEB-INF\lib\saaj.jar;%AXIS_HOME%\WEB-INF\lib\wsdl4j-1.5.1.jar;%AXIS_HOME%\WEB-INF\lib\activation.jar;%AXIS_HOME%\WEB-INF\lib\mail.jar;%AXIS_HOME%\WEB-INF\lib\xmlsec-1.4.4.jar

   c.
   CLASSPATH=.;%AXIS_CLASSPATH%


3. 執行方法
   java org.apache.axis.wsdl.WSDL2Java wsdl檔案全名 -o 相對目錄名稱
   
   例如:
   C:\>java org.apache.axis.wsdl.WSDL2Java outbound.wsdl -o wsdl_to_java_temp
   即代表會把 outbound.wsdl 轉換完成的檔案放在 C:\wsdl_to_java_temp 底下

JSTL 標籤

<c:out> 標籤
  <b>Hello, <c:out value="${user}" default="guest"/>.</b>
  可指定default值,避免 EL 表示式 user 之值為 null

  <b>Hello, <%=user%>.</b>
  <b>Hello, ${user}.</b>
  若 user 為 null 以上兩種方式,則 output 為 Hello, ______.

<c:forEach> 標籤
  以下兩個寫法結果都一樣,但使用 <c:forEach> 標籤卻精簡多了
  1.
  <table>
    <%
    String[] items = (String[]) request.getAttribute("movieList");
    String var = null;
    for (int i = 0; i < items.length; i++) {
      var = items[i];
    }
    %>
    <tr>
      <td><%= var %></td>
    </tr>
  </table>

  2.
  <table>
    <c:forEach var="movie" items="${movieList}">
      <tr>
        <td>${movie}</td>
      </tr>
    </c:forEach>
  </table>

  可用巢狀迴圈,範例如下:
  Servlet 程式碼
    String[] ary1 = {"a", "b", "c", "d"};
    String[] ary1 = {"e", "f", "g", "h"};
    java.util.List arrayList = new java.util.ArrayList();
    arrayList.add(ary1);
    arrayList.add(ary2);
    request.setAttribute("arrays", arrayList);

  JSP 程式碼
    <table>
      <c:forEach var="arrayEl" items="arrays">
        <c:forEach var="item" items="arrayEl">
          <tr>
            <td>${item}</td>
          </tr>
        </c:forEach>
      </c:forEach>
    </table>

<c:if> 標籤
  <c:if test="${user == 'admin'}">
    <jsp:include page="test.jsp">
  </c:if>
  上面的敘述代表若 user 變數值為 "admin"
  則 include test.jsp 頁面到網頁中
  但此標籤無法做到 else 的敘述,下一組標籤可以做到此需求

<c:choose>, <c:when>, and <c:otherwise> 標籤
  用法範例如下
    <c:choose>
        <c:when test="${a == 'test1'}">
            output string1
        </c:when>
       
        <c:when test="${a == 'test2'}">
            output string2
        </c:when>
       
        <c:otherwise>
            output string2
        </c:otherwise>
    </c:choose>

  以上被 <c:choose> 包住的判斷,包括<c:otherwise>,只會有一個被執行