精华内容
下载资源
问答
  • office中文繁简转换

    2013-07-07 13:49:02
    Office安装有“简繁转换”功能的话,视图-工具栏-选择“常用”工具栏(默认是选择的), 1. 可以在“常用”工具栏上看到“中文简繁转换”按钮; 2. 在“工具”项中也能看到“中文简繁转换”。 适用范围:Word 2002...
  • office繁简转换插件

    2017-10-16 00:30:07
    主要用于office繁简字体转换直接锲入在office文档插件里面转换
  • LibreOffice将office转换为pdf

    千次阅读 2016-05-18 13:37:12
    1.windows下office转换ok,但是txt乱码 将txt后缀修改为odt再转 2.linux下转换完后文件内容乱码(中文变成小方块): 将C:\Windows\Fonts下的字体拷贝到/usr/share/fonts/win,也可根据自己需要拷贝,我是全部拷贝...

    问题:

    1.windows下office转换ok,但是txt乱码

    将txt后缀修改为odt再转

    2.linux下转换完后文件内容乱码(中文变成小方块):

    将C:\Windows\Fonts下的字体拷贝到/usr/share/fonts/win,也可根据自己需要拷贝,我是全部拷贝。

    cd /usr/share/fonts/win

    mkfontscale

    mkfontdir

    fc-cache

    执行以上命令安装完字体再重启一下LibreOffice:

    先kill进程再执行以下命令(根据自己安装路径修改下面路径):

    /opt/libreoffice5.0/program/soffice  --headless --accept="socket,host=127.0.0.1,port=8100;urp;" --nofirststartwizard &

    3.linux下2操作完后txt乱码:

    一般windows下文件编码是gbk,linux下是utf-8,参照:http://wenku.baidu.com/link?url=cgPoZ_-ojngMIxfti6_JXrfY_6sYG14awan26mArK4xwo7SgulsPKs3DOZpiVq5jGR5eng4ulhVcVfiPGnPYstffHLqT3Fu_1iPC6O6Wrj_将文件转码再用LibreOffice转换即可

    4.maven项目jar包:

    <dependency>
        <groupId>com.artofsolving</groupId>
        <artifactId>jodconverter-maven-plugin</artifactId>
        <version>2.2.1</version>
        <exclusions>
            <exclusion>
                <groupId>com.artofsolving</groupId>
                <artifactId>jodconverter</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-jdk14</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk14</artifactId>
        <version>1.7.13</version>
    </dependency>
    
    
    <dependency>
        <groupId>org.openoffice</groupId>
        <artifactId>ridl</artifactId>
        <version>3.0.1</version>
    </dependency>
    
    <dependency>
        <groupId>org.openoffice</groupId>
        <artifactId>bootstrap-connector</artifactId>
        <version>0.1.1</version>
    </dependency>
    
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.4</version>
    </dependency>

    展开全文
  • 关于office转换pdf完美终极解决方案

    千次阅读 2016-03-12 11:54:15
    最近项目上面有个需求,将用户上传的office格式转换成pdf格式。下面记录下我走过的一些弯路,和得到的一些收获 1 使用java第三方api转换。 这个是我最开始的想法,因为java毕竟比较熟悉,学习成本,维护成本相对...
    最近项目上面有个需求,将用户上传的office格式转换成pdf格式。下面记录下我走过的一些弯路,和得到的一些收获
    
    1 使用java第三方api转换。
    这个是我最开始的想法,因为java毕竟比较熟悉,学习成本,维护成本相对较低。这个方案找过很多第三方,例如poi之类的,但是有两个缺点,1 性能低,对cpu压力大,2 兼容性差,很多格式或者特殊字符解析不出。
    2 使用openOffice
    openOffice也算是大名鼎鼎了,我使用的是另一个分支libreoffice。这个方案是在linux服务器上安装openOffice然后通过openOffice命令来转换pdf。
    性能问题基本解决,但是兼容性还是太差,特别是windowsOffice很多特有 格式无法读取或者乱码,而且需要安装微软中文字体还有可能涉及到侵权。
    3使用微软提供的com组件实现
    微软提供一个叫做SaveAsPDFandXPS的com组建来实现office转换成pdf。
    java通过jacob来调用com组件
    具体实现
    1 如果是web工程的话在jdk的bin目录下放置jacob-1.14.3-x64.dll
    2 需要一台windows服务器,将该功能单独部署
    3 这台windows服务需要安装office 和SaveAsPDFandXPS
    方案优点, 解决性能问题,完美解决兼容性问题。
    方案缺点, 需将转换服务单独部署,成为独立服务。需要windows服务器。需要实现linux系统和windows系统共享文件。这里感谢运维人员提供支持,通过磁盘挂载的方式实现共享文件。

    [img]http://dl2.iteye.com/upload/attachment/0115/7303/f76d40ee-a93a-34db-bfab-ac441fc739ce.png[/img]
    实现流程为:
    用户上传文件到web,web项目将用户上传的文件保存到文档服务器,然后调用部署在windows上的远程服务同时传递文件路径,该远程服务根据路径查找文档服务器上的文件并转换,然会返回相应的结果。
    稍微注意就是,看业务需求是同步转换还是异步转换,同步采用rpc机制调用远程服务,异步采用mq消息队列机制来实现远程服务调用。mq好处在于,可以最大化提升性能,因为可以通过队列来按顺序转换对应文件。
    展开全文
  • Java实现在线预览附件 office转换PDF

    万次阅读 2017-05-24 14:56:36
    Java实现在线预览附件 office转换PDF因为项目是做OA这一块,有很多附件需要实现在线预览附件,在网上也看了很多相关的资料。主要实现方式就是 (openoffice+swftools+flexpaper)和(aspose+pdfjs预览)。主要步骤:...

    Java实现在线预览附件 office转换PDF

    因为项目是做OA这一块,有很多附件需要实现在线预览附件,在网上也看了很多相关的资料。主要实现方式就是 (openoffice+swftools+flexpaper)和(aspose+pdfjs预览)。

    主要步骤:
    1.需要先将文档转换为PDF文件。
    2.用pdfjs预览PDF文件

    转换步骤:
    * 使用OpenOffice/Aspose 将ppt、word、excel、txt类型的文件转换为pdf

    预览步骤:
    * 高版本浏览器上,使用pdf.js直接预览PDF文件
    * 低版本浏览器上,使用swftools将PDF文件转换为swf文件,再使用flexpaper预览swf(没有做这个步骤)

    组件安装:
    Aspose
    由于OpenOffice的转换效果并不太佳,这里选择了Aspose
    在Aspose官网下载Aspose的Java版本,主要选择
    * Aspose.words
    * Aspose.cells(Excel)
    * Aspose.slides(PPT)
    * Aspose.pdf
    下载完成后,在工程中引用jar包即可。

    功能实现:
    这里采用的所有组件版本为:
    名称 版本
    Aspose.words 16.8.0
    Aspose.cells 9.0.0
    Aspose.slides 116.7.0
    Aspose.pdf 11.8.0
    文档转换为PDF

    使用Aspose进行文档转换很简单,直接引入相应的jar包,调用save方法,转换为PDF即可。

    注意:
    1. 使用Aspose时,每一个模块(words,cells)都可能有相同的类,如License类,SaveOptions类,SaveFormat类。而在各自模块使用时,一定要用对应模块的类,这个坑我已爬过。
    使用Aspose时,需要每次进行转换操作前调用设置License方法。

    package com.ybg.pf.oamodule.work.module.convert.util;
    
    
    import org.apache.log4j.Logger;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    /**
     * Aspose注册工具
     *
     * @author zhumin
     * @version 1.0.0
     *          2017年05月16日 15:58
     * @since Jdk1.7
     */
    public class AsposeLicenseUtil {
    
        private static InputStream inputStream = null;
    
        private static Logger logger = Logger.getLogger(AsposeLicenseUtil.class);
    
        /**
         * 获取License的输入流
         *
         * @return
         */
        private static InputStream getLicenseInput() {
            ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
            try {
                String path = contextClassLoader.getResource("license.xml").toURI().getPath();
                inputStream = new FileInputStream(path);
    
            } catch (Exception e) {
                logger.error("license not found!", e);
            }
            return inputStream;
        }
    
        /**
         * 设置License
         *
         * @return true表示已成功设置License, false表示失败
         */
        public static boolean setWordsLicense() {
            InputStream licenseInput = getLicenseInput();
            if (licenseInput != null) {
                try {
                    com.aspose.words.License aposeLic = new com.aspose.words.License();
                    aposeLic.setLicense(licenseInput);
                    return aposeLic.getIsLicensed();
                } catch (Exception e) {
                    logger.error("set words license error!", e);
                }
            }
            return false;
        }
    
        /**
         * 设置License
         *
         * @return true表示已成功设置License, false表示失败
         */
        public static boolean setCellsLicense() {
            InputStream licenseInput = getLicenseInput();
            if (licenseInput != null) {
                try {
                    com.aspose.cells.License aposeLic = new com.aspose.cells.License();
                    aposeLic.setLicense(licenseInput);
                    return true;
                } catch (Exception e) {
                    logger.error("set cells license error!", e);
                }
            }
            return false;
        }
    
        /**
         * 设置License
         *
         * @return true表示已成功设置License, false表示失败
         */
        public static boolean setSlidesLicense() {
            InputStream licenseInput = getLicenseInput();
            if (licenseInput != null) {
                try {
                    com.aspose.slides.License aposeLic = new com.aspose.slides.License();
                    aposeLic.setLicense(licenseInput);
                    return aposeLic.isLicensed();
                } catch (Exception e) {
                    logger.error("set ppt license error!", e);
                }
            }
            return false;
        }
    
        /**
         * 设置Aspose PDF的license
         * @return true表示设置成功,false表示设置失败
         */
        public static boolean setPdfLicense() {
            InputStream licenseInput = getLicenseInput();
            if (licenseInput != null) {
                try {
                    com.aspose.pdf.License aposeLic = new com.aspose.pdf.License();
                    aposeLic.setLicense(licenseInput);
                    return true;
                } catch (Exception e) {
                    logger.error("set pdf license error!", e);
                }
            }
            return false;
        }
    }
    

    word文档转换代码实例:

    package com.ybg.pf.oamodule.work.module.convert.service.impl;
    
    import com.aspose.words.Document;
    import com.aspose.words.PdfSaveOptions;
    import com.aspose.words.SaveFormat;
    import com.ybg.pf.oamodule.work.module.convert.domain.ConvertStatus;
    import com.ybg.pf.oamodule.work.module.convert.service.File2PdfService;
    import com.ybg.pf.oamodule.work.module.convert.util.AsposeLicenseUtil;
    import org.apache.log4j.Logger;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    
    /**
     * 将doc文档转换为pdf文件
     *
     * @author zhumin
     * @version 1.0.0
     *          2017年05月16日 15:58
     * @since Jdk1.7
     */
    public class Doc2PdfServiceImpl implements File2PdfService {
    
        private Logger logger = Logger.getLogger(getClass());
    
        @Override
        public ConvertStatus convert2Pdf(InputStream inputStream, OutputStream outputStream) {
            try {
                if (AsposeLicenseUtil.setWordsLicense()) {
    
                    Document doc = new Document(inputStream);
    
    //                insertWatermarkText(doc, "水印水印"); // 添加水印
    
                    PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
                    pdfSaveOptions.setSaveFormat(SaveFormat.PDF);
                    pdfSaveOptions.getOutlineOptions().setHeadingsOutlineLevels(3); // 设置3级doc书签需要保存到pdf的heading中
                    pdfSaveOptions.getOutlineOptions().setExpandedOutlineLevels(1); // 设置pdf中默认展开1级
    
                    doc.save(outputStream, pdfSaveOptions);
                    inputStream.close();
                    outputStream.flush();
                    outputStream.close();
                    return ConvertStatus.SUCCESS;
                } else {
                    return ConvertStatus.LICENSE_ERROR;
                }
            } catch (Exception e) {
                return ConvertStatus.CONVERT_DOC2PDF_ERROR;
            }
        }
    
    }
    

    其他格式就不附下面会提供代码下载。

    预览流程:先在后台下载附件到项目指定临时目录,在读取下载文件转换为PDF存储到临时目录

    这里写图片描述
    这是目录结构:convertFile附件下载存放目录 outputFilePDF存储目录

    package com.ybg.pf.oamodule.common.util;
    
    
    import com.ybg.pf.framework.library.util.FileRWUtils;
    import com.ybg.pf.framework.library.util.LogUtil;
    import com.ybg.pf.oamodule.work.module.convert.domain.ConvertStatus;
    import com.ybg.pf.oamodule.work.module.convert.service.File2PdfService;
    import com.ybg.pf.oamodule.work.module.convert.service.impl.Doc2PdfServiceImpl;
    import com.ybg.pf.oamodule.work.module.convert.service.impl.Excel2PdfServiceImpl;
    import com.ybg.pf.oamodule.work.module.convert.service.impl.PPT2PdfServiceImpl;
    import org.apache.commons.lang.StringUtils;
    
    import java.io.*;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    /**
     * Created by Administrator on 2017/5/11.
     * 在线预览工具类
     * 文件下载工具
     */
    public class PreviewUtils {
        //转换服务
        private static File2PdfService fileConvertService;
    
        /**
         * office转换PDF
         * @param fileName 需要转换的文件名
         * @return
         * @throws Exception
         */
        public static ConvertStatus officeConversionPDF(String fileName) throws Exception{
            //获取文件后缀
            String suffix = fileName.substring(fileName.lastIndexOf(".")+1,fileName.length());
            String fileNames = fileName.substring(0,fileName.lastIndexOf("."));
            //根据后缀判断文件类型实例化对应服务层
            if (StringUtils.equalsIgnoreCase(suffix,"docx") || StringUtils.equalsIgnoreCase(suffix,"doc")){
                fileConvertService = new Doc2PdfServiceImpl();
            }else if (StringUtils.equalsIgnoreCase(suffix,"pptx") || StringUtils.equalsIgnoreCase(suffix,"ppt")){
                fileConvertService = new PPT2PdfServiceImpl();
            }else if (StringUtils.equalsIgnoreCase(suffix,"xlsx") || StringUtils.equalsIgnoreCase(suffix,"xls")){
                fileConvertService = new Excel2PdfServiceImpl();
            }
            ConvertStatus convertStatus = null;
            //获取需要转换文档的所在路径
            File officeFile = new File(savePath()+File.separator+fileName);
            File outputFile = new File(outPDFPath(fileNames) +File.separator+ fileNames+".pdf");//PDF保存文件路径
            //如果文件是 PDF 不用转换直接复制到指定目录
            if (StringUtils.equalsIgnoreCase(suffix,"pdf")){
                FileRWUtils.copyFile(officeFile.getPath(),outPDFPath(fileNames));
                return convertStatus;
            }
            if (!outputFile.exists()){
                InputStream inputStream = new FileInputStream(officeFile);
                OutputStream outputStream = new FileOutputStream(outputFile);
                //开始转换
                convertStatus = fileConvertService.convert2Pdf(inputStream, outputStream);
            }
            return convertStatus;
        }
    
        /**
         * 根据PDF文件名获取PDF存储地址
         * @param fileName PDF文件名
         * @return
         *  没有加.toURI() 有可能中文路径会乱码 加上获取会出错
         */
        public static String outPDFPath(String fileName) throws Exception{
            String pathName = PreviewUtils.class.getClassLoader().getResource("").getPath();
            //文件保存位置 如果文件夹不存在创建文件夹
            File saveDir = new File(pathName+File.separator+"outputFile");
            if(!saveDir.exists()){
                saveDir.mkdir();
            }
            return saveDir.getPath();
        }
    
        /**
         * 获取文件保存路径
         * @return
         */
        public static String savePath(){
            String pathName = PreviewUtils.class.getClassLoader().getResource("").getPath();
            //文件保存位置 如果文件夹不存在创建文件夹
            File saveDir = new File(pathName+File.separator+"convertFile");
            if(!saveDir.exists()){
                saveDir.mkdir();
            }
            return saveDir.getPath();
        }
    
        /**
         * 从网络Url中下载文件
         * @param urlStr 下载地址
         * @param fileName 文件名
         * @param savePath  保存地址
         * @throws IOException
         */
        public static boolean  downLoadFromUrl(String urlStr,String fileName,String savePath){
            File file = new File(savePath+File.separator+fileName);
            //文件是否已存在
            if(file.exists()){
                return true;
            }
            try {
                URL url = new URL(urlStr);
                HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                //设置超时间为30秒
                conn.setConnectTimeout(30*1000);
                //防止屏蔽程序抓取而返回403错误
                conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
                //得到输入流
                InputStream inputStream = conn.getInputStream();
                //获取自己数组
                byte[] getData = readInputStream(inputStream);
                FileOutputStream fos = new FileOutputStream(file);
                if (getData == null){
                    return false;
                }
                fos.write(getData);
                if(fos!=null){
                    fos.close();
                }
                if(inputStream!=null){
                    inputStream.close();
                }
                if (conn.getResponseCode() == HttpURLConnection.HTTP_OK){
                    return true;
                }
            } catch (IOException e) {
                LogUtil.error("附件下载转换PDF出错!",e);
            }
            return false;
        }
    
        /**
         * 从输入流中获取字节数组
         * @param inputStream
         * @return
         * @throws IOException
         */
        public static  byte[] readInputStream(InputStream inputStream) throws IOException {
            byte[] buffer = new byte[1024];
            int len = 0;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while((len = inputStream.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            bos.close();
            return bos.toByteArray();
        }
    
    
    }
    

    这里写图片描述

    由于我们要集成到自己的工程中来,所以此处直接copy了viewer.html页面,修改为了我们工程需要的view_pdfjs.jsp ,其中做了一些修改删除了部分不需要的功能
    下面是我修改过后的预览页面 效果图:
    这里写图片描述

    <%@ page import="com.ybg.pf.oamodule.common.constant.JspCommonConstant" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%
    
        String qiyehaoProjectpath = JspCommonConstant.getProjectBasePath();
    %>
    <!DOCTYPE html>
    <!--
    Copyright 2012 Mozilla Foundation
    
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
    
    http://www.apache.org/licenses/LICENSE-2.0
    
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
    
    Adobe CMap resources are covered by their own copyright but the same license:
    
    Copyright 1990-2015 Adobe Systems Incorporated.
    
    See https://github.com/adobe-type-tools/cmap-resources
    -->
    <html dir="ltr" mozdisallowselectionprint moznomarginboxes>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
        <meta name="google" content="notranslate">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>PDF.js viewer</title>
        <link rel="stylesheet" href="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/viewer.css">
        <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/compatibility.js"></script>
        <!-- This snippet is used in production (included from viewer.html) -->
        <link rel="resource" type="application/l10n" href="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/locale/locale.properties">
        <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/l10n.js"></script>
        <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/build/pdf.js"></script>
        <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/debugger.js"></script>
        <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/viewer.js"></script>
        <script type="application/javascript">
            PDFJS.workerSrc = "<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/build/pdf.worker.js";
    
            /*
             PDFJS.onerror = function(message, moreInfo){
             var queryString = document.location.search.substring(1);
             var params = parseQueryStringRegexImpl(queryString);
             var file = 'file' in params ? params.file : null;
    
             // redirect to file
             if(file){
             location.href = file;
             }
             }
    
             function parseQueryStringRegexImpl(query){
             var reg = /([^\?\=\&]+)\=([^\&]*)/g;
             var obj = {};
             while (reg.exec (query)) {
             obj[RegExp.$1] = RegExp.$2;
             }
             return obj;
             }
             */
        </script>
    </head>
    
    <body tabindex="1" class="loadingInProgress">
    <div id="outerContainer">
    
        <div id="sidebarContainer">
            <div id="toolbarSidebar">
                <div class="splitToolbarButton toggled">
                    <button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" tabindex="2" data-l10n-id="thumbs">
                        <span data-l10n-id="thumbs_label">Thumbnails</span>
                    </button>
                    <button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="3" data-l10n-id="outline">
                        <span data-l10n-id="outline_label">Document Outline</span>
                    </button>
                    <button id="viewAttachments" class="toolbarButton group" title="Show Attachments" tabindex="4" data-l10n-id="attachments">
                        <span data-l10n-id="attachments_label">Attachments</span>
                    </button>
                </div>
            </div>
            <div id="sidebarContent">
                <div id="thumbnailView">
                </div>
                <div id="outlineView" class="hidden">
                </div>
                <div id="attachmentsView" class="hidden">
                </div>
            </div>
        </div>  <!-- sidebarContainer -->
    
        <div id="mainContainer">
            <div class="findbar hidden doorHanger hiddenSmallView" id="findbar">
                <label for="findInput" class="toolbarLabel" data-l10n-id="find_label">Find:</label>
                <input id="findInput" class="toolbarField" tabindex="91">
                <div class="splitToolbarButton">
                    <button class="toolbarButton findPrevious" title="" id="findPrevious" tabindex="92" data-l10n-id="find_previous">
                        <span data-l10n-id="find_previous_label">Previous</span>
                    </button>
                    <div class="splitToolbarButtonSeparator"></div>
                    <button class="toolbarButton findNext" title="" id="findNext" tabindex="93" data-l10n-id="find_next">
                        <span data-l10n-id="find_next_label">Next</span>
                    </button>
                </div>
                <input type="checkbox" id="findHighlightAll" class="toolbarField" tabindex="94">
                <label for="findHighlightAll" class="toolbarLabel" data-l10n-id="find_highlight">Highlight all</label>
                <input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95">
                <label for="findMatchCase" class="toolbarLabel" data-l10n-id="find_match_case_label">Match case</label>
                <span id="findResultsCount" class="toolbarLabel hidden"></span>
                <span id="findMsg" class="toolbarLabel"></span>
            </div>  <!-- findbar -->
    
            <div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
                <div id="secondaryToolbarButtonContainer">
                    <button id="secondaryPresentationMode" class="secondaryToolbarButton presentationMode visibleLargeView" title="Switch to Presentation Mode" tabindex="51" data-l10n-id="presentation_mode">
                        <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
                    </button>
    
                    <button style="display: none;" id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="52" data-l10n-id="open_file">
                        <span data-l10n-id="open_file_label">Open</span>
                    </button>
    
                    <button style="display: none;" id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="53" data-l10n-id="print">
                        <span data-l10n-id="print_label">Print</span>
                    </button>
    
                    <button style="display: none;" id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="54" data-l10n-id="download">
                        <span data-l10n-id="download_label">Download</span>
                    </button>
    
                    <a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView" title="Current view (copy or open in new window)" tabindex="55" data-l10n-id="bookmark">
                        <span data-l10n-id="bookmark_label">Current View</span>
                    </a>
    
                    <div class="horizontalToolbarSeparator visibleLargeView"></div>
    
                    <button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="56" data-l10n-id="first_page">
                        <span data-l10n-id="first_page_label">Go to First Page</span>
                    </button>
                    <button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="57" data-l10n-id="last_page">
                        <span data-l10n-id="last_page_label">Go to Last Page</span>
                    </button>
    
                    <div class="horizontalToolbarSeparator"></div>
    
                    <button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="58" data-l10n-id="page_rotate_cw">
                        <span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span>
                    </button>
                    <button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="59" data-l10n-id="page_rotate_ccw">
                        <span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span>
                    </button>
    
                    <div class="horizontalToolbarSeparator"></div>
    
                    <button id="toggleHandTool" class="secondaryToolbarButton handTool" title="Enable hand tool" tabindex="60" data-l10n-id="hand_tool_enable">
                        <span data-l10n-id="hand_tool_enable_label">Enable hand tool</span>
                    </button>
    
                    <div class="horizontalToolbarSeparator"></div>
    
                    <button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="61" data-l10n-id="document_properties">
                        <span data-l10n-id="document_properties_label">Document Properties…</span>
                    </button>
                </div>
            </div>  <!-- secondaryToolbar -->
    
            <div class="toolbar">
                <div id="toolbarContainer">
                    <div id="toolbarViewer">
                        <div id="toolbarViewerLeft">
                            <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="11" data-l10n-id="toggle_sidebar">
                                <span data-l10n-id="toggle_sidebar_label">Toggle Sidebar</span>
                            </button>
                            <div class="toolbarButtonSpacer"></div>
                            <button id="viewFind" class="toolbarButton group hiddenSmallView" title="Find in Document" tabindex="12" data-l10n-id="findbar">
                                <span data-l10n-id="findbar_label">Find</span>
                            </button>
                            <div class="splitToolbarButton">
                                <button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="13" data-l10n-id="previous">
                                    <span data-l10n-id="previous_label">Previous</span>
                                </button>
                                <div class="splitToolbarButtonSeparator"></div>
                                <button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="14" data-l10n-id="next">
                                    <span data-l10n-id="next_label">Next</span>
                                </button>
                            </div>
                            <label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
                            <input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="15">
                            <span id="numPages" class="toolbarLabel"></span>
                        </div>
                        <div id="toolbarViewerRight">
                            <button id="presentationMode" class="toolbarButton presentationMode hiddenLargeView" title="Switch to Presentation Mode" tabindex="31" data-l10n-id="presentation_mode">
                                <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
                            </button>
    
                            <button id="openFile" style="visibility:hidden" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="32" data-l10n-id="open_file">
                                <span data-l10n-id="open_file_label">Open</span>
                            </button>
    
                            <button id="print" style="visibility:hidden" class="toolbarButton print hiddenMediumView" title="Print" tabindex="33" data-l10n-id="print">
                                <span data-l10n-id="print_label">Print</span>
                            </button>
    
                            <button id="download" style="visibility:hidden" class="toolbarButton download hiddenMediumView" title="Download" tabindex="34" data-l10n-id="download">
                                <span data-l10n-id="download_label">Download</span>
                            </button>
                            <a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="35" data-l10n-id="bookmark">
                                <span data-l10n-id="bookmark_label">Current View</span>
                            </a>
    
                            <div class="verticalToolbarSeparator hiddenSmallView"></div>
    
                            <button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="36" data-l10n-id="tools">
                                <span data-l10n-id="tools_label">Tools</span>
                            </button>
                        </div>
                        <div class="outerCenter">
                            <div class="innerCenter" id="toolbarViewerMiddle">
                                <div class="splitToolbarButton">
                                    <button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="21" data-l10n-id="zoom_out">
                                        <span data-l10n-id="zoom_out_label">Zoom Out</span>
                                    </button>
                                    <div class="splitToolbarButtonSeparator"></div>
                                    <button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="22" data-l10n-id="zoom_in">
                                        <span data-l10n-id="zoom_in_label">Zoom In</span>
                                    </button>
                                </div>
                                <span id="scaleSelectContainer" class="dropdownToolbarButton">
                         <select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
                          <option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
                          <option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
                          <option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
                          <option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
                          <option id="customScaleOption" title="" value="custom"></option>
                          <option title="" value="0.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 50 }'>50%</option>
                          <option title="" value="0.75" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 75 }'>75%</option>
                          <option title="" value="1" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 100 }'>100%</option>
                          <option title="" value="1.25" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 125 }'>125%</option>
                          <option title="" value="1.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 150 }'>150%</option>
                          <option title="" value="2" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 200 }'>200%</option>
                          <option title="" value="3" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 300 }'>300%</option>
                          <option title="" value="4" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 400 }'>400%</option>
                        </select>
                      </span>
                            </div>
                        </div>
                    </div>
                    <div id="loadingBar">
                        <div class="progress">
                            <div class="glimmer">
                            </div>
                        </div>
                    </div>
                </div>
            </div>
    
            <menu type="context" id="viewerContextMenu">
                <menuitem id="contextFirstPage" label="First Page"
                          data-l10n-id="first_page"></menuitem>
                <menuitem id="contextLastPage" label="Last Page"
                          data-l10n-id="last_page"></menuitem>
                <menuitem id="contextPageRotateCw" label="Rotate Clockwise"
                          data-l10n-id="page_rotate_cw"></menuitem>
                <menuitem id="contextPageRotateCcw" label="Rotate Counter-Clockwise"
                          data-l10n-id="page_rotate_ccw"></menuitem>
            </menu>
    
            <div id="viewerContainer" tabindex="0">
                <div id="viewer" class="pdfViewer"></div>
            </div>
    
            <div id="errorWrapper" hidden='true'>
                <div id="errorMessageLeft">
                    <span id="errorMessage"></span>
                    <button id="errorShowMore" data-l10n-id="error_more_info">
                        More Information
                    </button>
                    <button id="errorShowLess" data-l10n-id="error_less_info" hidden='true'>
                        Less Information
                    </button>
                </div>
                <div id="errorMessageRight">
                    <button id="errorClose" data-l10n-id="error_close">
                        Close
                    </button>
                </div>
                <div class="clearBoth"></div>
                <textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea>
            </div>
        </div> <!-- mainContainer -->
    
        <div id="overlayContainer" class="hidden">
            <div id="passwordOverlay" class="container hidden">
                <div class="dialog">
                    <div class="row">
                        <p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
                    </div>
                    <div class="row">
                        <!-- The type="password" attribute is set via script, to prevent warnings in Firefox for all http:// documents. -->
                        <input id="password" class="toolbarField">
                    </div>
                    <div class="buttonRow">
                        <button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button>
                        <button id="passwordSubmit" class="overlayButton"><span data-l10n-id="password_ok">OK</span></button>
                    </div>
                </div>
            </div>
            <div id="documentPropertiesOverlay" class="container hidden">
                <div class="dialog">
                    <div class="row">
                        <span data-l10n-id="document_properties_file_name">File name:</span> <p id="fileNameField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_file_size">File size:</span> <p id="fileSizeField">-</p>
                    </div>
                    <div class="separator"></div>
                    <div class="row">
                        <span data-l10n-id="document_properties_title">Title:</span> <p id="titleField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_author">Author:</span> <p id="authorField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_subject">Subject:</span> <p id="subjectField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_keywords">Keywords:</span> <p id="keywordsField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_creation_date">Creation Date:</span> <p id="creationDateField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_modification_date">Modification Date:</span> <p id="modificationDateField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_creator">Creator:</span> <p id="creatorField">-</p>
                    </div>
                    <div class="separator"></div>
                    <div class="row">
                        <span data-l10n-id="document_properties_producer">PDF Producer:</span> <p id="producerField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_version">PDF Version:</span> <p id="versionField">-</p>
                    </div>
                    <div class="row">
                        <span data-l10n-id="document_properties_page_count">Page Count:</span> <p id="pageCountField">-</p>
                    </div>
                    <div class="buttonRow">
                        <button id="documentPropertiesClose" class="overlayButton"><span data-l10n-id="document_properties_close">Close</span></button>
                    </div>
                </div>
            </div>
        </div>  <!-- overlayContainer -->
    
    </div> <!-- outerContainer -->
    <div id="printContainer"></div>
    <div id="mozPrintCallback-shim" hidden>
        <style>
            @media print {
                #printContainer div {
                    page-break-after: always;
                    page-break-inside: avoid;
                }
            }
        </style>
        <style scoped>
            #mozPrintCallback-shim {
                position: fixed;
                top: 0;
                left: 0;
                height: 100%;
                width: 100%;
                z-index: 9999999;
    
                display: block;
                text-align: center;
                background-color: rgba(0, 0, 0, 0.5);
            }
            #mozPrintCallback-shim[hidden] {
                display: none;
            }
            @media print {
                #mozPrintCallback-shim {
                    display: none;
                }
            }
    
            #mozPrintCallback-shim .mozPrintCallback-dialog-box {
                display: inline-block;
                margin: -50px auto 0;
                position: relative;
                top: 45%;
                left: 0;
                min-width: 220px;
                max-width: 400px;
    
                padding: 9px;
    
                border: 1px solid hsla(0, 0%, 0%, .5);
                border-radius: 2px;
                box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    
                background-color: #474747;
    
                color: hsl(0, 0%, 85%);
                font-size: 16px;
                line-height: 20px;
            }
            #mozPrintCallback-shim .progress-row {
                clear: both;
                padding: 1em 0;
            }
            #mozPrintCallback-shim progress {
                width: 100%;
            }
            #mozPrintCallback-shim .relative-progress {
                clear: both;
                float: right;
            }
            #mozPrintCallback-shim .progress-actions {
                clear: both;
            }
        </style>
        <div class="mozPrintCallback-dialog-box">
            <!-- TODO: Localise the following strings -->
            Preparing document for printing...
            <div class="progress-row">
                <progress value="0" max="100"></progress>
                <span class="relative-progress">0%</span>
            </div>
            <div class="progress-actions">
                <input type="button" value="Cancel" class="mozPrintCallback-cancel">
            </div>
        </div>
    </div>
    
    </body>
    </html>

    预览
    pdf.js使用参数file来指定需要预览的文件。例如我们的view_pdfjs.jsp对应的controller地址为:http://localhost:8080/pf_oamodule/openmodule/showPDF?file=test.pdf

    跨域
    如果pdf.js预览页面同pdf文件资源在同一个域下,此处可以忽略。

    pdf.js使用的异步请求来请求的pdf文件资源,这也就意味着会存在跨域问题。pdf.js中主动检测了file参数对应的地址是否是同一个域中。

    用 H5 iframe标签嵌套加载PDF页面

    <%@ page import="com.ybg.pf.oamodule.common.constant.JspCommonConstant" %>
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%
    
        String qiyehaoProjectpath = JspCommonConstant.getProjectBasePath();
    %>
    <html>
    <head>
        <title>${pdfName}</title>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
        <script type="text/javascript" src="<%=qiyehaoProjectpath%>/static/js/zepto.min.js"></script>
    </head>
    <style>
        *{margin:0;padding:0}
    </style>
    <body>
    <iframe  src="<c:url value="/openmodule/showPDF" />?file=<%=qiyehaoProjectpath%>/openmodule/displayPDF?pdfName=${pdfName}"
            width="100%" height="100%"></iframe>
    </body>
    </html>

    我目前采用的方式是封装一个同域下的controller请求,该controller请求会拿到请求资源然后再回写。实现controller代码:

    package com.ybg.pf.oamodule.work.module_open;
    
    import com.ybg.pf.framework.library.util.LogUtil;
    import com.ybg.pf.oamodule.common.util.PreviewUtils;
    import org.apache.commons.io.IOUtils;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.OutputStream;
    
    /**
     * Created by Administrator on 2017/5/11.
     * 在线预览PDF
     */
    @Controller
    @RequestMapping("/openmodule")
    public class ShowPDFController {
    
        /**
         * 要在线预览PDF直接调用这个控制器会自己去加载页面
         * @param request
         * @param pdfName 必须传递参数PDF文件名
         * @return
         */
        @RequestMapping(value = "/loadPDF" , method = RequestMethod.GET)
        public ModelAndView loadPDF(HttpServletRequest request,@RequestParam String pdfName){
            pdfName = pdfName.replaceAll("\\+","%2B");
            request.setAttribute("pdfName",pdfName);
    
            return new ModelAndView("pdf/show");
        }
    
        /**
         * 调用PDF显示页面
         * @return
         */
        @RequestMapping(value = "/showPDF" , method = RequestMethod.GET)
        public ModelAndView showPDF(){
            return new ModelAndView("pdf/view_pdfjs");
        }
    
    
        /**
         * 返回一个PDF给页面加载
         * @param response
         * @param request
         * @param pdfName PDF文件名
         */
        @RequestMapping(value = "/displayPDF" , method = RequestMethod.GET)
        public void displayPDF(HttpServletResponse response,HttpServletRequest request,@RequestParam String pdfName) {
            try {
                File file = new File(PreviewUtils.outPDFPath(pdfName) +File.separator+ pdfName+".pdf");//PDF保存文件路径
                FileInputStream fileInputStream = new FileInputStream(file);
                response.setHeader("Content-Disposition", "attachment;fileName="+pdfName+".pdf");
                response.setContentType("multipart/form-data");
                OutputStream outputStream = response.getOutputStream();
                IOUtils.write(IOUtils.toByteArray(fileInputStream), outputStream);
            } catch(Exception e) {
                LogUtil.error("PDF读取出错!");
            }
        }
    }
    

    主要实现流程就是这些,做完发现在线预览也没有想像的那么难,最后附上核心代码可以下载参考!

    Java在线预览核心代码下载
    aspose-slides-16.7.0 - aspose-words-16.8.0 包
    aspose-cells-9.0.0 - aspose-pdf-11.8.0 包

    展开全文
  • Office 2000 简繁转换加载项 是可以将在Excel中的简体中文转换为繁体中文
  • Office XP简繁转换加载项是可以将XP系统中的Excel在的简体中文转换为繁体中文
  • 繁体中文xp系统,登陆管理员账号安装office简繁转换增益集,切换到一般用户后,看不到简繁转换按钮。登入管理员账号,给一般user增加administrator权限,登入一般user账号,可以看到简繁转换按钮。再登入管理员账号...

    繁体中文xp系统,登陆管理员账号安装office简繁转换增益集,切换到一般用户后,看不到简繁转换按钮。登入管理员账号,给一般user增加administrator权限,登入一般user账号,可以看到简繁转换按钮。再登入管理员账号,取消user的administrator权限。

    转载于:https://www.cnblogs.com/jerain6312/articles/4073834.html

    展开全文
  • OFFICE 文档在线预览方案很多: 服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览,比如flexpaper Office文档直接转换为SWF,通过网页加载Flash预览 微软的Office365 在浏览器中直接打开 转换为html ...
  • 实际上,简繁转换是Office2007的一个COM加载项,取决于"/Microsoft Office/Office12/ADDINS/TCSCCONV.DLL"这个文件,文件版本为12.0.4513.1000,正常情况下当启动Office2007的时候这个文件应该会自动加载,但是如果...
  • pdf转换为word,无需安装office即可完成转换,这个软件的转换速度和版面的还原能力都是比较好的,而且有中文汉化版的便于操作,只需转换word格式的朋友推荐使用。
  • office高级操作第一讲——重点感叹号转换 建议使用office365或者office2019/2016 废话少说,直接上图 选中内容,按ctrl+h 也是选中,按ctrl+h,重复步骤忽略 选中,按ctrl+h,重复步骤忽略 全部替换,再...
  • SoftMaker Office Pro 2021是由德国 Softmaker 公司推出的一款类似于Microsoft Office的办公软件套件,号称媲美微软Office的办公软件。
  •   默认安装的英文版Office 2007 standard (也就是仅包括word, excel, powerpoint, outlook简装版)   转换简体和繁体中文的时候:   在word 2007的菜单里: Review> "Chinese ...
  • Office XP 简繁转换加载项<BR> 适用于 Access 2002 Excel 2002 PowerPoint 2002
  • Microsoft Office 97 是一款超级经典的并珍藏在威航软件园网盘中多年的微软Office办公软件,是微软公司于1997年5月12日推出Office 97中文版,Windows 98系统时代的装机必备办公神器,集办公应用和网络技术于一体且...
  • Office2016 Visio2016 Project2016零售版转换VL版

    万次阅读 热门讨论 2018-03-01 15:28:38
    在MSDN网站上下载的Office2016是零售版本的,我们在使用一些KMS工具激活时,需要先转换为VL(批量授权版本)版,可以将下列文本另存为bat文件,以管理员运行根据提示即可完成转换 链接:...
  • LibreOffice实现对office文档的转换

    千次阅读 2018-10-18 10:50:41
    package ... import java.io.File; import java.util.Date; import org.artofsolving.jodconverter.OfficeDocumentConverter; import org.artofsolving.jodconverter.office.DefaultOfficeMan...
  • office添加繁简体转换 本人所在的公司是一间港资公司,很多香港同事习惯繁体,而我们内地的同事则习惯简体,于是免不了要进行繁简体转换,这时候就要装一个office的插件来达到这样的功能,如下: 1、没装插件...
  • OpenOffice自从2002年发布第一个版本1.0.1以来已经过去了15个年头... 作为Office工具的翻版,OpenOffice在文本文档、电子表格、演示文稿、绘图、数据库也是功能完备,而基于Apache2.0发布的OpenOffice可以完全自由使用
  • office word excel 2010 2003 批量 转换

    千次阅读 2012-11-04 19:38:35
    自从office2007和2010推广应用之后,常碰到的是03与07/10格式的读取与转换问题,对于此问题的解决大多是下载一个兼容包使得03下能读07和10的文档。尽管此方法能解决,但当你不知对方是否会操作电脑或者对方是否是...
  • HTML Filter 是由北京红樱枫软件有限公司依据HTML Ver 4.01/CSS式样,研制和开发的MS Office系列文档到HTML转换的通用程序库。便于用户实现对多种文档的统一管理,编辑,检索和浏览。用户可以使用本产品,实现文档...
  • 所有中文汉字(CJK统一字符) [一-龥] or [一-﨩] 35     所有中文标点 [!一-龥^1-^127] 36     所有非数字字符 [!0-9] ...
  • 依托云储存,WPS Office 2019 开启了跨平台移动办公时代。电脑中存储的文档,均可通过 WPS Office 2019 打开,并通过【云服务】转换成在线协同文档。该协同文档还可通过 WPS Office 移动端或 WPS 文档微信小程序打开...
  • WPS Office for Android 中文版 金山 Office 安卓版WPS Office for Android 中文版 金山 Office 安卓版 WPS Office for Android 特色简介: 1、文档编辑掌上进行,随时随地享受办公乐趣:金山WPS Office移动版支持...
  • onlyoffice字体
  • http://www.xiazaizhijia.com/soft/59442.html office2007是微软Office产品史上最具创新与革命性的一个版本,全新设计的用户界面、稳定安全的文件格式、无缝高效的沟通协作,office2007免费版几乎包括了Word2007、...
  • OfficeSuite Documents – 文档 • 兼容 Microsoft Word Office 格式 – DOC、.DOCX、.DOCM + .RTF、.TXT • 支持 OpenDocument 等常用格式 – .ODT、.ODS 和.ODP • 具有 70 多种字体的字体包,可最大限度实现兼容 ...
  • 使用Office批量打印精灵可将Word、Excel、PPT文档转换为PDF文档,可将单个文档转换为单个PDF,注意自动保存PDF功能只对 pdfFactory 3.52 中文版有效。 使用前需安装: Office批量打印精灵4.0或更高版,可到依云...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,117
精华内容 10,046
关键字:

office换中文