Java实现office(word,excel,ppt)文档在线预览

想要实现word或者其他office文件的在线预览,大部分都是用的两种方式,一种是使用openoffice转换之后再通过其他插件预览,还有一种方式就是通过POI读取内容然后预览。

一、使用openoffice方式实现word预览

主要思路是:

1.通过第三方工具openoffice,将word、excel、ppt、txt等文件转换为pdf文件

2.通过swfTools将pdf文件转换成swf格式的文件

3.通过FlexPaper文档组件在页面上进行展示

我使用的工具版本:

openof:3.4.1

swfTools:1007

FlexPaper:这个关系不大,我随便下的一个。推荐使用1.5.1

JODConverter:需要jar包,如果是maven管理直接引用就可以

操作步骤:

1.office准备

下载openoffice:

Apache OpenOffice - Official Download

从过往文件,其他语言中找到中文版3.4.1的版本

下载后,解压缩,安装

然后找到安装目录下的program 文件夹

在目录下运行

soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard

如果运行失败,可能会有提示,那就加上 .\ 在运行试一下

 扫VX 领Java资料,前端,测试,python等等资料都有

这样openoffice的服务就开启了。

将flexpaper文件中的js文件夹(包含了flexpaper_flash_debug.js,flexpaper_flash.js,jquery.js,这三个js文件主要是预览swf文件的插件)拷贝至网站根目录;将FlexPaperViewer.swf拷贝至网站根目录下(该文件主要是用在网页中播放swf文件的播放器)

项目结构:

 

页面代码:

fileUpload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"  
    pageEncoding="UTF-8"%>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>文档在线预览系统</title>  
<style>  
    body {margin-top:100px;background:#fff;font-family: Verdana, Tahoma;}  
    a {color:#CE4614;}  
    #msg-box {color: #CE4614; font-size:0.9em;text-align:center;}  
    #msg-box .logo {border-bottom:5px solid #ECE5D9;margin-bottom:20px;padding-bottom:10px;}  
    #msg-box .title {font-size:1.4em;font-weight:bold;margin:0 0 30px 0;}  
    #msg-box .nav {margin-top:20px;}  
</style>  
  
</head>  
<body>  
<div id="msg-box">  
    <form name="form1"  method="post" enctype="multipart/form-data" action="docUploadConvertAction.jsp">  
        <div class="title">  
            请上传要处理的文件,过程可能需要几分钟,请稍候片刻。  
        </div>  
        <p>  
            <input name="file1" type="file">  
        </p>  
        <p>  
            <input type="submit" name="Submit" value="上传">  
        </p>  
    </form >  
</div>  
</body>  
</html>

docUploadConvertAction.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
  
<%@page import="java.io.*"%>  
<%@page import="java.util.Enumeration"%>  
<%@page import="com.oreilly.servlet.MultipartRequest"%>  
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>  
<%@page import="filetest.DocConverter"%>  
<%  
//文件上传采用cos组件上传,可更换为commons-fileupload上传,文件上传后,保存在upload文件夹  
//获取文件上传路径  
String saveDirectory =application.getRealPath("/")+"upload";  
//打印上传路径信息  
System.out.println(saveDirectory);  
//每个文件最大50m  
int maxPostSize = 50 * 1024 * 1024 ;  
//采用cos缺省的命名策略,重名后加1,2,3...如果不加dfp重名将覆盖  
DefaultFileRenamePolicy dfp = new DefaultFileRenamePolicy();  
//response的编码为"UTF-8",同时采用缺省的文件名冲突解决策略,实现上传,如果不加dfp重名将覆盖  
MultipartRequest multi = new MultipartRequest(request, saveDirectory, maxPostSize,"UTF-8",dfp);  
//MultipartRequest multi = new MultipartRequest(request, saveDirectory, maxPostSize,"UTF-8");  
//输出反馈信息  
 Enumeration files = multi.getFileNames();  
     while (files.hasMoreElements()) {  
        System.err.println("ccc");  
       String name = (String)files.nextElement();  
       File f = multi.getFile(name);  
       if(f!=null){  
         String fileName = multi.getFilesystemName(name);  
         //获取上传文件的扩展名  
         String extName=fileName.substring(fileName.lastIndexOf(".")+1);  
         //文件全路径  
         String lastFileName= saveDirectory+"\\" + fileName;  
         //获取需要转换的文件名,将路径名中的'\'替换为'/'  
         String converfilename = saveDirectory.replaceAll("\\\\", "/")+"/"+fileName;  
         System.out.println(converfilename);  
         //调用转换类DocConverter,并将需要转换的文件传递给该类的构造方法  
         DocConverter d = new DocConverter(converfilename);  
         //调用conver方法开始转换,先执行doc2pdf()将office文件转换为pdf;再执行pdf2swf()将pdf转换为swf;  
         d.conver();  
         //调用getswfPath()方法,打印转换后的swf文件路径  
         System.out.println(d.getswfPath());  
         //生成swf相对路径,以便传递给flexpaper播放器  
         String swfpath = "upload"+d.getswfPath().substring(d.getswfPath().lastIndexOf("/"));  
         System.out.println(swfpath);  
         //将相对路径放入sessio中保存  
         session.setAttribute("swfpath", swfpath);  
         out.println("上传的文件:"+lastFileName);  
         out.println("文件类型"+extName);  
         out.println("<hr>");  
       }  
     }  
  
%>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>Insert title here</title>  
<style>  
    body {margin-top:100px;background:#fff;font-family: Verdana, Tahoma;}  
    a {color:#CE4614;}  
    #msg-box {color: #CE4614; font-size:0.9em;text-align:center;}  
    #msg-box .logo {border-bottom:5px solid #ECE5D9;margin-bottom:20px;padding-bottom:10px;}  
    #msg-box .title {font-size:1.4em;font-weight:bold;margin:0 0 30px 0;}  
    #msg-box .nav {margin-top:20px;}  
</style>  
</head>  
<body>  
    <div>  
        <form name="viewForm" id="form_swf" action="documentView.jsp" method="POST">  
            <input type='submit' value='预览' class='BUTTON SUBMIT'/>  
        </form>  
    </div>  
</body>  
</html>

documentView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
<%  
    String swfFilePath=session.getAttribute("swfpath").toString();  
%>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<script type="text/javascript" src="js/jquery.js"></script>  
<script type="text/javascript" src="js/flexpaper_flash.js"></script>  
<script type="text/javascript" src="js/flexpaper_flash_debug.js"></script>  
<style type="text/css" media="screen">   
            html, body  { height:100%; }  
            body { margin:0; padding:0; overflow:auto; }     
            #flashContent { display:none; }  
        </style>   
  
<title>文档在线预览系统</title>  
</head>  
<body>   
        <div style="position:absolute;left:50px;top:10px;">  
            <a id="viewerPlaceHolder" style="width:820px;height:650px;display:block"></a>  
              
            <script type="text/javascript">   
                var fp = new FlexPaperViewer(     
                         'FlexPaperViewer',  
                         'viewerPlaceHolder', { config : {  
                         SwfFile : escape('<%=swfFilePath%>'),  
                         Scale : 0.6,   
                         ZoomTransition : 'easeOut',  
                         ZoomTime : 0.5,  
                         ZoomInterval : 0.2,  
                         FitPageOnLoad : true,  
                         FitWidthOnLoad : false,  
                         FullScreenAsMaxWindow : false,  
                         ProgressiveLoading : false,  
                         MinZoomSize : 0.2,  
                         MaxZoomSize : 5,  
                         SearchMatchAll : false,  
                         InitViewMode : 'SinglePage',  
                           
                         ViewModeToolsVisible : true,  
                         ZoomToolsVisible : true,  
                         NavToolsVisible : true,  
                         CursorToolsVisible : true,  
                         SearchToolsVisible : true,  
                          
                         localeChain: 'en_US'  
                         }});  
            </script>              
        </div>  
</body>  
</html>

转换类:

DocConverter.java

package filetest;

import java.io.BufferedInputStream;  
import java.io.File;  
import java.io.IOException;  
import java.io.InputStream;  
  
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;  
  
/** 
 * doc docx格式转换 
 */  
public class DocConverter {  
    private static final int environment = 1;// 环境 1:windows 2:linux  
    private String fileString;// (只涉及pdf2swf路径问题)  
    private String outputPath = "";// 输入路径 ,如果不设置就输出在默认的位置  
    private String fileName;  
    private File pdfFile;  
    private File swfFile;  
    private File docFile;  
      
    public DocConverter(String fileString) {  
        ini(fileString);  
    }  
  
    /** 
     * 重新设置file 
     *  
     * @param fileString 
     */  
    public void setFile(String fileString) {  
        ini(fileString);  
    }  
  
    /** 
     * 初始化 
     *  
     * @param fileString 
     */  
    private void ini(String fileString) {  
        this.fileString = fileString;  
        fileName = fileString.substring(0, fileString.lastIndexOf("."));  
        docFile = new File(fileString);  
        pdfFile = new File(fileName + ".pdf");  
        swfFile = new File(fileName + ".swf");  
    }  
      
    /** 
     * 转为PDF 
     *  
     * @param file 
     */  
    private void doc2pdf() throws Exception {  
        if (docFile.exists()) {  
            if (!pdfFile.exists()) {  
                OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);  
                try {  
                    connection.connect();  
                    DocumentConverter converter = new OpenOfficeDocumentConverter(connection);  
                    converter.convert(docFile, pdfFile);  
                    // close the connection  
                    connection.disconnect();  
                    System.out.println("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****");  
                } catch (java.net.ConnectException e) {  
                    e.printStackTrace();  
                    System.out.println("****swf转换器异常,openoffice服务未启动!****");  
                    throw e;  
                } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {  
                    e.printStackTrace();  
                    System.out.println("****swf转换器异常,读取转换文件失败****");  
                    throw e;  
                } catch (Exception e) {  
                    e.printStackTrace();  
                    throw e;  
                }  
            } else {  
                System.out.println("****已经转换为pdf,不需要再进行转化****");  
            }  
        } else {  
            System.out.println("****swf转换器异常,需要转换的文档不存在,无法转换****");  
        }  
    }  
      
    /** 
     * 转换成 swf 
     */  
    @SuppressWarnings("unused")  
    private void pdf2swf() throws Exception {  
        Runtime r = Runtime.getRuntime();  
        if (!swfFile.exists()) {  
            if (pdfFile.exists()) {  
                if (environment == 1) {// windows环境处理  
                    try {  
                        Process p = r.exec("D:/pdf2swf/pdf2swf.exe "+ pdfFile.getPath() + " -o "+ swfFile.getPath() + " -T 9");  
                        //Process p=new Process();
                        System.out.print(loadStream(p.getInputStream()));  
                        System.err.print(loadStream(p.getErrorStream()));  
                        System.out.print(loadStream(p.getInputStream()));  
                        System.err.println("****swf转换成功,文件输出:"  
                                + swfFile.getPath() + "****");  
                        if (pdfFile.exists()) {  
                            pdfFile.delete();  
                        }  
  
                    } catch (IOException e) {  
                        e.printStackTrace();  
                        throw e;  
                    }  
                } else if (environment == 2) {// linux环境处理  
                    try {  
                        Process p = r.exec("pdf2swf " + pdfFile.getPath()  
                                + " -o " + swfFile.getPath() + " -T 9");  
                        System.out.print(loadStream(p.getInputStream()));  
                        System.err.print(loadStream(p.getErrorStream()));  
                        System.err.println("****swf转换成功,文件输出:"  
                                + swfFile.getPath() + "****");  
                        if (pdfFile.exists()) {  
                            pdfFile.delete();  
                        }  
                    } catch (Exception e) {  
                        e.printStackTrace();  
                        throw e;  
                    }  
                }  
            } else {  
                System.out.println("****pdf不存在,无法转换****");  
            }  
        } else {  
            System.out.println("****swf已经存在不需要转换****");  
        }  
    }  
  
    static String loadStream(InputStream in) throws IOException {  
  
        int ptr = 0;  
        in = new BufferedInputStream(in);  
        StringBuffer buffer = new StringBuffer();  
  
        while ((ptr = in.read()) != -1) {  
            buffer.append((char) ptr);  
        }  
  
        return buffer.toString();  
    }  
    /** 
     * 转换主方法 
     */  
    @SuppressWarnings("unused")  
    public boolean conver() {  
  
        if (swfFile.exists()) {  
            System.out.println("****swf转换器开始工作,该文件已经转换为swf****");  
            return true;  
        }  
  
        if (environment == 1) {  
            System.out.println("****swf转换器开始工作,当前设置运行环境windows****");  
        } else {  
            System.out.println("****swf转换器开始工作,当前设置运行环境linux****");  
        }  
        try {  
            doc2pdf();  
            pdf2swf();  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
  
        if (swfFile.exists()) {  
            return true;  
        } else {  
            return false;  
        }  
    }  
  
    /** 
     * 返回文件路径 
     *  
     * @param s 
     */  
    public String getswfPath() {  
        if (swfFile.exists()) {  
            String tempString = swfFile.getPath();  
            tempString = tempString.replaceAll("\\\\", "/");  
            return tempString;  
        } else {  
            return "";  
        }  
  
    }  
    /** 
     * 设置输出路径 
     */  
    public void setOutputPath(String outputPath) {  
        this.outputPath = outputPath;  
        if (!outputPath.equals("")) {  
            String realName = fileName.substring(fileName.lastIndexOf("/"),  
                    fileName.lastIndexOf("."));  
            if (outputPath.charAt(outputPath.length()) == '/') {  
                swfFile = new File(outputPath + realName + ".swf");  
            } else {  
                swfFile = new File(outputPath + realName + ".swf");  
            }  
        }  
    }  
  
}

然后运行。

中间遇到的问题,存放上传的upload文件夹要创建。

存放pdf2swf的位置的代码有问题,不知道为什么我第一次运行失败后,修改为正确地址,然后重启重写了很多次还是报错地址错误,最后将推荐哦那个样的代码放到新的项目里却可以正常运行不报错。

运行结果:

 

二、利用jodconverter(基于OpenOffice服务)将文件转化为html格式或者pdf格式(不成熟):

 扫VX 领Java资料,前端,测试,python等等资料都有

package org.pan.poi.poi;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.text.SimpleDateFormat;
import java.util.Date;

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;
/**
 * @包名 org.pan.poi.poi
 * @创建人 蒋文章
 * @日期 2018/4/23 0023
 * @时间 15:39
 * @描述
 * 利用jodconverter(基于OpenOffice服务)将文件(*.doc、*.docx、*.xls、*.ppt)转化为html格式或者pdf格式,
 * 使用前请检查OpenOffice服务是否已经开启, OpenOffice进程名称:soffice.exe | soffice.bin
 */
public class Doc2HtmlUtil {

    private static Doc2HtmlUtil doc2HtmlUtil;

    /**
     * 获取Doc2HtmlUtil实例
     */
    public static synchronized Doc2HtmlUtil getDoc2HtmlUtilInstance() {
        if (doc2HtmlUtil == null) {
            doc2HtmlUtil = new Doc2HtmlUtil();
        }
        return doc2HtmlUtil;
    }

    /**
     * 转换文件成html
     *
     * @param fromFileInputStream:
     * @throws IOException
     */
    public String file2Html(InputStream fromFileInputStream, String toFilePath,String type) throws IOException {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timesuffix = sdf.format(date);
        String docFileName = null;
        String htmFileName = null;
        if("doc".equals(type)){
            docFileName = "doc_" + timesuffix + ".doc";
            htmFileName = "doc_" + timesuffix + ".html";
        }else if("docx".equals(type)){
            docFileName = "docx_" + timesuffix + ".docx";
            htmFileName = "docx_" + timesuffix + ".html";
        }else if("xls".equals(type)){
            docFileName = "xls_" + timesuffix + ".xls";
            htmFileName = "xls_" + timesuffix + ".html";
        }else if("ppt".equals(type)){
            docFileName = "ppt_" + timesuffix + ".ppt";
            htmFileName = "ppt_" + timesuffix + ".html";
        }else{
            return null;
        }

        File htmlOutputFile = new File(toFilePath + File.separatorChar + htmFileName);
        File docInputFile = new File(toFilePath + File.separatorChar + docFileName);
        if (htmlOutputFile.exists())
            htmlOutputFile.delete();
        htmlOutputFile.createNewFile();
        if (docInputFile.exists())
            docInputFile.delete();
        docInputFile.createNewFile();
        /**
         * 由fromFileInputStream构建输入文件
         */
        try {
            OutputStream os = new FileOutputStream(docInputFile);
            int bytesRead = 0;
            byte[] buffer = new byte[1024 * 8];
            while ((bytesRead = fromFileInputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }

            os.close();
            fromFileInputStream.close();
        } catch (IOException e) {
        }

        OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
        try {
            connection.connect();
        } catch (ConnectException e) {
            System.err.println("文件转换出错,请检查OpenOffice服务是否启动。");
        }
        // convert
        DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
        converter.convert(docInputFile, htmlOutputFile);
        connection.disconnect();
        // 转换完之后删除word文件
        docInputFile.delete();
        return htmFileName;
    }

    /**
     * 转换文件成pdf
     *
     * @param fromFileInputStream:
     * @throws IOException
     */
    public String file2pdf(InputStream fromFileInputStream, String toFilePath,String type) throws IOException {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timesuffix = sdf.format(date);
        String docFileName = null;
        String htmFileName = null;
        if("doc".equals(type)){
            docFileName = "doc_" + timesuffix + ".doc";
            htmFileName = "doc_" + timesuffix + ".pdf";
        }else if("docx".equals(type)){
            docFileName = "docx_" + timesuffix + ".docx";
            htmFileName = "docx_" + timesuffix + ".pdf";
        }else if("xls".equals(type)){
            docFileName = "xls_" + timesuffix + ".xls";
            htmFileName = "xls_" + timesuffix + ".pdf";
        }else if("ppt".equals(type)){
            docFileName = "ppt_" + timesuffix + ".ppt";
            htmFileName = "ppt_" + timesuffix + ".pdf";
        }else{
            return null;
        }

        File htmlOutputFile = new File(toFilePath + File.separatorChar + htmFileName);
        File docInputFile = new File(toFilePath + File.separatorChar + docFileName);
        if (htmlOutputFile.exists())
            htmlOutputFile.delete();
        htmlOutputFile.createNewFile();
        if (docInputFile.exists())
            docInputFile.delete();
        docInputFile.createNewFile();
        /**
         * 由fromFileInputStream构建输入文件
         */
        try {
            OutputStream os = new FileOutputStream(docInputFile);
            int bytesRead = 0;
            byte[] buffer = new byte[1024 * 8];
            while ((bytesRead = fromFileInputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }

            os.close();
            fromFileInputStream.close();
        } catch (IOException e) {
        }

        OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
        try {
            connection.connect();
        } catch (ConnectException e) {
            System.err.println("文件转换出错,请检查OpenOffice服务是否启动。");
        }
        // convert
        DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
        converter.convert(docInputFile, htmlOutputFile);
        connection.disconnect();
        // 转换完之后删除word文件
        docInputFile.delete();
        return htmFileName;
    }

    public static void main(String[] args) throws IOException {
        Doc2HtmlUtil coc2HtmlUtil = getDoc2HtmlUtilInstance();
        File file = null;
        FileInputStream fileInputStream = null;

       /* file = new File("D:/poi-test/exportExcel.xls");
        fileInputStream = new FileInputStream(file);
//      coc2HtmlUtil.file2Html(fileInputStream, "D:/poi-test/openOffice/xls","xls");
        coc2HtmlUtil.file2pdf(fileInputStream, "D:/poi-test/openOffice/xls","xls");*/

        file = new File("F:/test/JavaWeb.doc");
        fileInputStream = new FileInputStream(file);
        coc2HtmlUtil.file2Html(fileInputStream, "F:/test","doc");
     //  coc2HtmlUtil.file2pdf(fileInputStream, "F:/test","doc");

  /*      file = new File("D:/poi-test/周报模版.ppt");
        fileInputStream = new FileInputStream(file);
//      coc2HtmlUtil.file2Html(fileInputStream, "D:/poi-test/openOffice/ppt","ppt");
        coc2HtmlUtil.file2pdf(fileInputStream, "D:/poi-test/openOffice/ppt","ppt");

        file = new File("D:/poi-test/test.docx");
        fileInputStream = new FileInputStream(file);
//      coc2HtmlUtil.file2Html(fileInputStream, "D:/poi-test/openOffice/docx","docx");
        coc2HtmlUtil.file2pdf(fileInputStream, "D:/poi-test/openOffice/docx","docx");*/

    }

}

三、使用poi读取word内容(不成熟):

package org.pan.poi.poi;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;

import org.apache.commons.io.FileUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;

/**
 * @author panmingshuai
 * @description
 * @Time 2018年4月2日 下午5:46:30
 *
 */
public class WordTest {
    @SuppressWarnings("resource")
    public static void main(String[] args) throws Exception {
        /**
         * 读取doc文档
         * */
         FileInputStream in = FileUtils.openInputStream(new
         File("F:\\物流知识点.doc"));
         HWPFDocument doc = new HWPFDocument(in);
         Range range = doc.getRange();
         for(int i=0; i<range.numParagraphs(); i++){
         System.out.println(
                 range.getParagraph(i).text());
         }
         String docText = range.text();
         System.out.println(docText);
         in.close();

        /**

 扫VX 领Java资料,前端,测试,python等等资料都有

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值