分享

poi PPT 在线预览

 WindySky 2016-08-17
web 中在线预览office 是个头疼的问题。 今天项目刚好做完一个PPT在线预览的功能   在这里分享给大家
 
思路:
     获取网络PPT 文件 将PPT每一页的幻灯片都转换成单张图片  用流输出到页面展示
     1, 首先获取PPT格式  PPT格式无非两种 PPTX,PPT
     2,获取PPT幻灯片页数传递到JSP中
     3,JSP循环获取每页PPT
上代码:
         首先获取在线PPT 文件  并且获取PPT幻灯片页数




/**
 * 本类应用了Apache POI系统库,POI 是 Apache 下的 Jakata 项目的一个子项目,主要用于提供 Java 操作 Microsoft Office 办公套件如 Excel,Word,Powerpoint 等文件的 API。
 */

public class ConvertPPTFileToImage {


public ConvertPPTFileToImage() {

}
/**
*  PPTX 格式的处理
* @param filePath  图片网络路径URL 
* @param page   页数
* @param orignalPPTFileName 文件名
* @param imageFormatNameString  创建图片格式 (JPG,PNG,JPEG...等等)
* @param outputStream   输出
* @throws Exception
* 本来字体是要设置成PPT的字体  但是上传到linux 时候linux需要自己上传字体 否则所有中文都会变成乱码  口口口  无法显示   所以这里只
         * 使用宋体  
*如果大家想用其他字体 同样也是 linux 服务器的情况下  请自己上传字体到linux 中避免中文无法显示   下面会介绍如何上传字体到linux 中
*/

public static void convertPPTXtoImage(String filePath,int page,String orignalPPTFileName, String imageFormatNameString, OutputStream outputStream) throws Exception {
/**
* 多文件转码处理避免有中文或者特殊字符无法读取
*/

InputStream orignalPPTFileInputStream =null;
   String encodeName="";
        String igs[]=orignalPPTFileName.split("/");
           for(int x=0;x<igs.length;x++){
            if(x==igs.length-1){
              encodeName+=URLEncoder.encode(igs[x]).replace("+","%20");
            }else{
               encodeName+=URLEncoder.encode(igs[x]).replace("+","%20")+"/";
            }
           }
           URL url=new URL(filePath+encodeName);
           HttpURLConnection conn = (HttpURLConnection)url.openConnection();
           conn.setRequestMethod("GET");   //使用get
           orignalPPTFileInputStream=conn.getInputStream();


//FileOutputStream orignalPPTFileOutputStream =null;
/**
*  org.apache.poi.hslf, 这个包只支持 PowerPoint 2007 以前的 ppt 文档解析. 因为 Office 2007 的文件底层实现方案(OOXML)和以前的版本(OLE2)有根本的变化。
*  支持 office 2007 的包为: org.apache.poi.xslf 
*/

XMLSlideShow oneSlideShow =null;
try{
try {
oneSlideShow = new XMLSlideShow(orignalPPTFileInputStream);
} catch (IOException e) {
e.printStackTrace();
}
/**
* 获得PPT每页的尺寸大小(宽和高度)
*/

Dimension onePPTPageSize = oneSlideShow.getPageSize();
/**
* 获得PPT文件中的所有的PPT页面,并转换为一张张的播放片
*/

XSLFSlide[] pptPageXSLFSlideArray = oneSlideShow.getSlides();
if(pptPageXSLFSlideArray.length<=0||page>=pptPageXSLFSlideArray.length){
return ;
}
/**
* 下面的XML配置文件定义转换后的图片内的文字字体,否则将会出现转换后的图片内的中文为乱码
*/

String xmlFontFormat1="<xml-fragment xmlns:a=\"http://schemas./drawingml/2006/main\" xmlns:r=\"http://schemas./officeDocument/2006/relationships\" xmlns:p=\"http://schemas./presentationml/2006/main\">";
String xmlFontFormat2="<a:rPr lang=\"zh-CN\" altLang=\"en-US\" dirty=\"0\" smtClean=\"0\"> ";
String xmlFontFormat3="<a:latin typeface=\"+mj-ea\"/> ";
String xmlFontFormat4="</a:rPr>";
String xmlFontFormat5="</xml-fragment>";
StringBuffer xmlFontFormatStringBuffer=new StringBuffer();
xmlFontFormatStringBuffer.append(xmlFontFormat1);
xmlFontFormatStringBuffer.append(xmlFontFormat2);
xmlFontFormatStringBuffer.append(xmlFontFormat3);
xmlFontFormatStringBuffer.append(xmlFontFormat4);
xmlFontFormatStringBuffer.append(xmlFontFormat5);

/**
*设置字体为宋体,解决中文乱码问题 
*/

           CTSlide oneCTSlide=pptPageXSLFSlideArray[page].getXmlObject();
           CTGroupShape oneCTGroupShape = oneCTSlide.getCSld().getSpTree();
           CTShape[] oneCTShapeArray = oneCTGroupShape.getSpArray();
           for (CTShape oneCTShape : oneCTShapeArray) {
               CTTextBody oneCTTextBody = oneCTShape.getTxBody();
               if (null == oneCTTextBody){
                   continue;
               }
               CTTextParagraph[] oneCTTextParagraph = oneCTTextBody.getPArray();               
               CTTextFont oneCTTextFont =null;
try {
oneCTTextFont = CTTextFont.Factory.parse(xmlFontFormatStringBuffer.toString());
}
catch (XmlException e) {
e.printStackTrace();
}
               for (CTTextParagraph textParagraph : oneCTTextParagraph) {
                   CTRegularTextRun[] oneCTRegularTextRunArray = textParagraph.getRArray();
                   for (CTRegularTextRun oneCTRegularTextRun : oneCTRegularTextRunArray) {
                       CTTextCharacterProperties oneCTTextCharacterProperties=oneCTRegularTextRun.getRPr();
                       oneCTTextCharacterProperties.setLatin(oneCTTextFont);
                   }
               }
           }
/**
* 创建BufferedImage对象,图象的尺寸为原来PPT的每页的尺寸
*/

BufferedImage oneBufferedImage = new BufferedImage(onePPTPageSize.width, onePPTPageSize.height, BufferedImage.TYPE_INT_RGB);
Graphics2D oneGraphics2D = oneBufferedImage.createGraphics();
/**
* 将PPT文件中的每个页面中的相关内容画到转换后的图片中
*/

pptPageXSLFSlideArray[page].draw(oneGraphics2D);
/**
* 设置图片的存放路径和图片的格式,注意生成的文件路径为绝对路径,最终获得各个图像文件所对应的输出流对象
*/

try {
ImageIO.write(oneBufferedImage, imageFormatNameString, outputStream);
} catch (IOException e) {
e.printStackTrace();
}
//}
}
finally{
try {
if(orignalPPTFileInputStream != null ){
orignalPPTFileInputStream.close();
}

catch (IOException e) {
e.printStackTrace();
}
}
}



/**
*  PPT 格式的处理
* @param filePath  图片网络路径URL 
* @param page   页数
* @param orignalPPTFileName 文件名
* @param imageFormatNameString  创建图片格式 (JPG,PNG,JPEG...等等)
* @param outputStream   输出
* @throws Exception
*  本来是设置成PPT的字体  但是上传到linux 时候linux需要自己上传字体 否则所有中文都会变成乱码  口口口  无法显示   所以这里只使用宋体  
* 如果大家想用其他字体 同样也是 linux 服务器的情况下  请自己上传字体到linux 中避免中文无法显示   下面会介绍如何上传字体到linux 中
*/

public static void convertPPTtoImage(String filePath,int page,String orignalPPTFileName, String imageFormatNameString,OutputStream outputStream) throws Exception {
/**
* convertReturnResult代表转换的结果,返回 false则表示转换不成功
*/

InputStream orignalPPTFileInputStream =null;
   String encodeName="";
        String igs[]=orignalPPTFileName.split("/");
           for(int x=0;x<igs.length;x++){
            if(x==igs.length-1){
              encodeName+=URLEncoder.encode(igs[x]).replace("+","%20");
            }else{
               encodeName+=URLEncoder.encode(igs[x]).replace("+","%20")+"/";
            }
           }
           URL url=new URL(filePath+encodeName);
           HttpURLConnection conn = (HttpURLConnection)url.openConnection();
           conn.setRequestMethod("GET");  
           orignalPPTFileInputStream=conn.getInputStream();
SlideShow oneSlideShow =null;
try{
try {
oneSlideShow = new SlideShow(orignalPPTFileInputStream);
} catch (IOException e) {
e.printStackTrace();
}
/**
* 获得PPT每页的尺寸大小(宽和高度)
*/

Dimension onePPTPageSize = oneSlideShow.getPageSize();
/**
* 获得PPT文件中的所有的PPT页面(获得每一张幻灯片),并转换为一张张的播放片
*/

Slide[] pptPageSlideArray = oneSlideShow.getSlides();
/**
* 下面的循环的主要功能是实现对PPT文件中的每一张幻灯片进行转换和操作。
*/

if(pptPageSlideArray.length<=0||page>=pptPageSlideArray.length){
return ;
}

TextRun[] textRunsArray = pptPageSlideArray[page].getTextRuns();
for (int textRunsArrayIndex = 0; textRunsArrayIndex < textRunsArray.length; textRunsArrayIndex++) {
RichTextRun[] pptRichTextRunsArray = textRunsArray[textRunsArrayIndex].getRichTextRuns();
for (int pptRichTextRunsArrayIndex = 0; pptRichTextRunsArrayIndex < pptRichTextRunsArray.length; pptRichTextRunsArrayIndex++) {
/**原来是直接设置为宋体,这样会使得转换后的图片上的文字与原PPT的文字不一致,应该改变为应用PPT本身的字体名
* pptRichTextRunsArray[pptRichTextRunsArrayIndex].setFontIndex(1);
* pptRichTextRunsArray[pptRichTextRunsArrayIndex].setFontName("宋体");
*/ 
/**
* 获得某个文本框内的字体名字符串,并识别是否为null(未正确地获得相关的字体名字符串),则设置为默认的字体名——宋体
* 但如果PPT文件在WPS中保存过,则pptRichTextRunsArray[pptRichTextRunsArrayIndex].getFontSize()的值可能为0或者26040。因此,
* 首先识别当前文本框内的字体尺寸是否为0或者大于26040,则设置默认的字体尺寸。
*/

int currentFontSize = pptRichTextRunsArray[pptRichTextRunsArrayIndex].getFontSize();
if((currentFontSize <=0)||(currentFontSize >=26040)){
pptRichTextRunsArray[pptRichTextRunsArrayIndex].setFontSize(30);
}

String currentFontName=pptRichTextRunsArray[pptRichTextRunsArrayIndex].getFontName();
/**
* 本来是设置成PPT的字体  但是上传到linux 时候linux需要自己上传字体 否则所有中文都会变成乱码  口口口  无法显示   所以这里只使用宋体  
* 如果大家想用其他字体 同样也是 linux 服务器的情况下  请自己上传字体到linux 中避免中文无法显示   下面会介绍如何上传字体到linux 中
*/

/* if(currentFontName == null){  */  
 int index = pptRichTextRunsArray[pptRichTextRunsArrayIndex].getFontIndex();
 pptRichTextRunsArray[pptRichTextRunsArrayIndex].setFontIndex(1);
 pptRichTextRunsArray[pptRichTextRunsArrayIndex].setFontName("宋体");
//}
/*else{
pptRichTextRunsArray[pptRichTextRunsArrayIndex].setFontName(currentFontName);
}*/
/**
* 应用 pptRichTextRunsArray[pptRichTextRunsArrayIndex].getText() 可以获得其中的文字
* int pptRichTextRunsNumberIndex = pptRichTextRunsArray[pptRichTextRunsArrayIndex].getFontIndex();
String fontNameForPPTText = pptRichTextRunsArray[pptRichTextRunsArrayIndex].getFontName();
*/

}
}
/**
* 下面的代码是获取某一页PPT中的第一个备注文字串
    System.out.println("备注文字:" + pptPageSlideArray[pptPageSlideIndex].getNotesSheet().getTextRuns()[0].getText());
    */
/**
* 创建BufferedImage对象,图象的尺寸为原来PPT的每页的尺寸
*/

BufferedImage oneBufferedImage = new BufferedImage(onePPTPageSize.width, onePPTPageSize.height, BufferedImage.TYPE_INT_RGB);
Graphics2D oneGraphics2D = oneBufferedImage.createGraphics();
oneGraphics2D.setFont(new Font("宋体", Font.PLAIN, 12));

/**
* 设置转换后的图片的背景颜色为白色
* oneGraphics2D.setPaint(Color.white);
oneGraphics2D.fill(new Rectangle2D.Float(0, 0, onePPTPageSize.width ,onePPTPageSize.height));
*/

pptPageSlideArray[page].draw(oneGraphics2D);
/**
* 图像文件的格式字符串为“jpg”、“jpeg”、"bmp"、"png"、 "gif"、"tiff"等,将转换后的各个图片文件保存到指定的目录中
*/

try {
ImageIO.write(oneBufferedImage, imageFormatNameString, outputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
finally{
try {
if(orignalPPTFileInputStream != null ){
orignalPPTFileInputStream.close();
}

catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*    检查文件是否为ppt或者pptx格式 
* @param orignalPPTFileName需要转换的原始PPT的文件名称
* @return
*/

public static short checkOrignalFileFormat(String  orignalPPTFileName) {
/**
* PPT格式的识别结果, =0 不是PPT或者PPTX的格式文件, =1 代表*.ppt 格式, =2  代表 *.pptx 格式
*/

short pptORpptxFormatFile = 0;
/**
* 识别需要转换的原始PPT的文件是否为真正的PPT文件
*/

String orignalPPTFileSuffixName = null;
if (orignalPPTFileName != null && orignalPPTFileName.lastIndexOf(".") != -1) {
/**
* 获得需要转换的原始ppt或者pptx的文件扩展名,返回的结果应该为“ppt”或者"pptx"字符串
*/

orignalPPTFileSuffixName = orignalPPTFileName.substring(orignalPPTFileName.lastIndexOf(".") );
/** 
* 识别是否为.ppt格式
*/

if (".ppt".equals(orignalPPTFileSuffixName)) {
pptORpptxFormatFile = 1;
}
/**
* 识别是否为.pptx格式
*/

else if (".pptx".equals(orignalPPTFileSuffixName)) {
pptORpptxFormatFile = 2;
}
/**
* 如果不是.ppt格式或者*.pptx格式,则表示为非法的文件格式,则不能进行转换,符合检测的结果编码为0
*/

}
return pptORpptxFormatFile;
}

/**
* 判断文件是否存在   并且返回PPT幻灯片的页数
* @param filePath   文件路径URL
* @param orignalPPTFileName  文件名
* @return
* @throws Exception
*/

public static int getPPTImgCount(String filePath,String orignalPPTFileName) throws Exception{
/**
* 对文件名转码处理 避免有中文和特殊字符时无法获取图片
*/

SlideShow oneSlideShow =null;
XMLSlideShow oneSlideShow2 =null;
InputStream orignalPPTFileInputStream =null;
   String encodeName="";
        String igs[]=orignalPPTFileName.split("/");
           for(int x=0;x<igs.length;x++){
            if(x==igs.length-1){
              encodeName+=URLEncoder.encode(igs[x]).replace("+","%20");
            }else{
               encodeName+=URLEncoder.encode(igs[x]).replace("+","%20")+"/";
            }
           }
           URL url=new URL(filePath+encodeName);
           HttpURLConnection conn = (HttpURLConnection)url.openConnection();
           conn.setRequestMethod("GET"); 
            int state = conn.getResponseCode();
            if( state!=200){
            return 0;
            }
             
           orignalPPTFileInputStream=conn.getInputStream();

int count=0;
switch(checkOrignalFileFormat(orignalPPTFileName)){
case 0:
System.out.println("待转换的PPT文件不存在或者不是PPT和PPTX格式的文件!");
break;
case 1:
try {
oneSlideShow = new SlideShow(orignalPPTFileInputStream);
} catch (IOException e) {
e.printStackTrace();
return 0;
}
count= oneSlideShow.getSlides().length;
break;
case 2:
try {
oneSlideShow2 = new XMLSlideShow(orignalPPTFileInputStream);
} catch (IOException e) {
e.printStackTrace();
return 0;
}
count = oneSlideShow2.getSlides().length;
break;
}
return count;
}

}
      /**
          获取PPT页数到JSP 创建图片
      */

@RequestMapping(value = "ppts")
public String get(HttpServletRequest request,int id,String isFav) throws Exception{
request.setAttribute("pptCount", ConvertPPTFileToImage.getPPTImgCount(uploadHelper, data.value.getCASE_INTRO_URL()));
return "dtl";
}


    /**
          获取PPT图片
          page  为幻灯片页数
      */

@RequestMapping(value = "loaddtlppt")
public void  loadDtlPpt(HttpServletRequest req,HttpServletResponse rsp,int page) throws Exception{
String loadPath= (String) req.getSession().getAttribute("loadPptUrl");
String imageFormatNameString ="jpeg";
rsp.setHeader("Pragma", "No-cache");
rsp.setHeader("Cache-Control", "No-cache");
rsp.setDateHeader("Expires", 0);
// 指定生成的响应是图片
rsp.setContentType("image/jpeg");
switch(ConvertPPTFileToImage.checkOrignalFileFormat(loadPath)){
case 0:
System.out.println("待转换的PPT文件不存在或者不是PPT和PPTX格式的文件!");
break;
case 1:
ConvertPPTFileToImage.convertPPTtoImage([自行改成PPT文件路径],page,[文件名], imageFormatNameString,rsp.getOutputStream());
break;
case 2:
ConvertPPTFileToImage.convertPPTXtoImage([自行改成PPT文件路径],page,[文件名],imageFormatNameString,rsp.getOutputStream());
break;
}

}









-------------------------jsp  代码---------------------------


ppts.jsp   html


<c:forEach begin="1" end="${pptCount}" varStatus="status">
<img alt="方案详情" src="<c:url value="/${base}loaddtlppt?page=${status.index-1}" />&time=<%=System.currentTimeMillis()%>" />
</c:forEach>




html  end









//---------------------------------------------------------------
相关JAR    没有用mave 也可以直接下载 poi 包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.10-FINAL</version>
</dependency>


<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi-scratchpad</artifactId>
   <version>3.11-beta3</version>
</dependency>




Linux 上传  字体   


首先 找到 windows 下的字体 这里以宋体为例子
C:\Windows\Fonts\simsun.ttc   
上传到  linux jar 的 font 目录下
$HOME_PATH/jar/lib/fonts/fallback 目录下
(如果fonts下没有 fallback 目录自己创建    然后重启tomcat 就可以了  ,注意 是 ttc 后缀 不是ttf)




就此完毕  希望能帮到大家 ---------------第一次写







    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约