PPT&PDF文件转换成图片上传OSS

PPTPDFIMAGE

先把文件上传至本地,再去读取文件转变上传。

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>fontbox</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-mock</artifactId>
    <version>2.0.8</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.9</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.9</version>
</dependency>
//文件保存路径,因为需要先把文件保存在本地
@Value("${myapp.path.upload}")
private String uploadPath;

PPT2IMAGE

@ApiOperation(value = "PPT文件转图片上传")
@PostMapping("/ppt2ImageUpload")
public String doPPTtoImage(MultipartFile file) {
    String fileName = file.getOriginalFilename();
    String fileSuffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());
    String localFileName = System.currentTimeMillis() + fileSuffix;
    String filePath = uploadPath + File.separator + localFileName;
    File localFile = new File(filePath);
    File imagePath = new File(uploadPath);
    if (!imagePath.exists()) {
        imagePath.mkdirs();
    }
    try {
        file.transferTo(localFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
    File file1 = new File(filePath);
    return convertPPTtoImage(file1);
}

public String convertPPTtoImage(File file) {
    List<SysFile> sysList = new ArrayList<>();
    long start = System.currentTimeMillis();

    int isppt = checkFile(file);
    if (isppt < 0) {
        System.out.println("this file isn't ppt or pptx.");
        return null;
    }
    try {
        FileInputStream is = new FileInputStream(file);
        Dimension pgsize = null;
        Object[] slide = null;

        if (isppt == 0) {
            SlideShow ppt = new SlideShow(is);
            is.close();
            pgsize = ppt.getPageSize();
            slide = ppt.getSlides();
        } else if (isppt == 1) {
            XMLSlideShow xppt = new XMLSlideShow(is);
            is.close();
            pgsize = xppt.getPageSize();
            slide = xppt.getSlides();
        }

        for (int i = 0; i < slide.length; i++) {
            System.out.println("Processing Page " + (i + 1) + "... ");
            BufferedImage img = new BufferedImage(pgsize.width,
                    pgsize.height, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = img.createGraphics();
            graphics.setPaint(Color.white);
            graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width,
                    pgsize.height));

            if (isppt == 0) {
                Slide ss = (Slide) slide[i];
                ss.draw(graphics);
            } else {
                XSLFSlide xss = (XSLFSlide) slide[i];
                xss.draw(graphics);
            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
            ImageIO.write(img, "png", baos);
            byte[] bytes = baos.toByteArray();//转换成字节
            BASE64Encoder encoder = new BASE64Encoder();
            String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
            png_base64 = "data:image/jpg;base64," + png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
            System.out.println("值为:" + "data:image/jpg;base64," + png_base64);

            MultipartFile multipartFile = Base64DecodeMultipartFile.base64Convert(png_base64);
            String result = "";
            String fKey = renamePic(multipartFile.getOriginalFilename());
            SysFile f = new SysFile();
            InputStream inputStream = null;
            try {
                inputStream = multipartFile.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 上传至第三方云服务或服务器
            result = fileManageFactory.getFileManage(null).inputStreamUpload(inputStream, fKey, multipartFile);
            f.setLocation(2);
            // 保存数据信息至数据库
            f.setName(i + multipartFile.getOriginalFilename());
            f.setSize(multipartFile.getSize());
            f.setType(multipartFile.getContentType());
            f.setFKey(fKey);
            f.setUrl(result);
            fileService.save(f);
            sysList.add(f);
        }
        System.out.println("completed in " + (System.currentTimeMillis() - start) + " ms.");
    } catch (FileNotFoundException e) {
        System.out.println(e);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return JsonUtils.serialize(sysList);
}

public static int checkFile(File file) {
    int isppt = -1;
    String filename = file.getName();
    String suffixname = null;
    if (filename != null && filename.indexOf(".") != -1) {
        suffixname = filename.substring(filename.indexOf("."));
        if (suffixname.equals(".ppt")) {
            isppt = 0;
        } else if (suffixname.equals(".pptx")) {
            isppt = 1;
        }
    }
    return isppt;
}

PDF2IMAGE

public String pdf2Image(MultipartFile file) {
    String fileName = file.getOriginalFilename();
    String fileSuffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());
    String localFileName = System.currentTimeMillis() + fileSuffix;
    String filePath = uploadPath + File.separator + localFileName;
    File localFile = new File(filePath);
    try {
        file.transferTo(localFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
    List<SysFile> sysList = new ArrayList<>();
    try {
        File pdfFile = new File(filePath);

        uploadPDF(filePath, sysList, pdfFile);

    } catch (IOException e) {
        e.printStackTrace();
    }
    return JsonUtils.serialize(sysList);
}
private void uploadPDF(String filePath, List<SysFile> sysList, File pdfFile) throws IOException {
        PDDocument pdDocument;
        int dot = pdfFile.getName().lastIndexOf('.');
        String imagePDFName = pdfFile.getName().substring(0, dot); // 获取图片文件名
        String imgFolderPath = null;


        pdDocument = PDDocument.load(pdfFile);
        PDFRenderer renderer = new PDFRenderer(pdDocument);
        /* dpi越大转换后越清晰,相对转换速度越慢 */
        PdfReader reader = new PdfReader(filePath);
        int pages = reader.getNumberOfPages();
        StringBuffer imgFilePath = null;
        for (int i = 0; i < pages; i++) {
            String imgFilePathPrefix = imgFolderPath + pdfFile.separator + imagePDFName;
            imgFilePath = new StringBuffer();
            imgFilePath.append(imgFilePathPrefix);
            imgFilePath.append("_");
            imgFilePath.append(String.valueOf(i + 1));
            imgFilePath.append(".png");
            BufferedImage image = renderer.renderImageWithDPI(i, 300);

			//最后使用 BufferedImage对象 image去做图片上传即可 
            SysFile f = getSysFile(i, image);
            sysList.add(f);
        }
    }

PPT2PDF

因为很多虚拟机,他可能没有合适的字体,这样的话就会导致直接由PPT转的图片出现乱码问题,所以如果直接PPT转图片出现乱码,可以尝试先把PPT转成PDF再转图片

环境准备

下载jar包:

链接:https://pan.baidu.com/s/1BIKJuK_g9hJb5nJkBROwmA 提取码:4bge

导入maven

先把jar包导入到项目中:

http://blogimgbucketxun.oss-cn-beijing.aliyuncs.com/xiaoYiXun/common/20200822_16110630.png

<dependency>
    <groupId>aspose.slides</groupId>
    <artifactId>slides</artifactId>
    <version>19.3</version>
    <scope>system</scope>
    <systemPath>${basedir}/lib/aspose.slides-19.3.jar</systemPath>
</dependency>

代码

license.xml

<License>
  <Data>
    <Products>
      <Product>Aspose.Total for Java</Product>      
    </Products>
    <EditionType>Enterprise</EditionType>
    <SubscriptionExpiry>20991231</SubscriptionExpiry>
    <LicenseExpiry>20991231</LicenseExpiry>
    <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
  </Data>
  <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>

PdfOperation.java

import com.aspose.slides.License;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * @author 萧一旬
 * @date Create in 10:41 2020/8/21
 */
@Component
public class PdfOperation {

    private static InputStream license;


    /**
     * 获取license
     *
     * @return
     */
    public boolean getLicense() {

        boolean result = false;
        license = PdfOperation.class.getClassLoader().getResourceAsStream("license.xml");
        if (license != null) {
            License aposeLic = new License();
            aposeLic.setLicense(license);
            result = true;
        }
        return result;
    }

    /**
     * @param file       PPT文件
     * @param uploadPath PDF文件存放地址
     * @return 转换好的PDF文件地址,后续需要根据这个地址去拿PDF转换成图片
     */
    public String convertPDF(File file, String uploadPath) {
        // 验证License
        if (!getLicense()) {
            return "验证License失败";
        }
        try {
            FileInputStream fileInput = new FileInputStream(file);
            Presentation pres = new Presentation(fileInput);
            String path = uploadPath + "\\" + System.currentTimeMillis() + ".pdf";
            FileOutputStream out = new FileOutputStream(new File(path));
            pres.save(out, SaveFormat.Pdf);
            out.close();
            return path;
        } catch (Exception e) {
            e.getMessage();
        }
        return null;
    }
}

PPT转PDF再转图片上传

/**
 * 前面的部分和PPT2IMAGE的操作一样,变的只有 convertPPTtoImage 方法
 * @param file
 * @return
 */
public String convertPPTtoImage(File file) {
    //先将PPT转成PDF
    String path = pdfOperation.convertPDF(file, uploadPath);

    if (StringUtils.isNotBlank(path)) {
        List<SysFile> sysList = new ArrayList<>();
        try {
            File pdfFile = new File(path);

            uploadPDF(path, sysList, pdfFile);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return JsonUtils.serialize(sysList);
    }
    return null;
}

打包注意

使用这种方式引入的依赖,如果没有配置,那么这个jar在你打包的时候就不会被加进去,所以可能你线下行的通,线上就抛异常找不到类。

所以可以把jar包加到本地仓库,然后引用本地仓库的坐标,再打包就可以解决这个问题

安装指定文件到本地仓库命令:mvn install:install-file
-DgroupId=<groupId> : 设置项目代码的包名(一般用组织名)
-DartifactId=<artifactId> : 设置项目名或模块名
-Dversion=1.0.0 : 版本号
-Dpackaging=jar : 什么类型的文件(jar包)
-Dfile=<myfile.jar> : 指定jar文件路径与文件名(同目录只需文件名)

实例

mvn install:install-file -Dfile=C:\Users\16329\Desktop\aspose.slides-19.3.jar -DgroupId=org.apache.thrift -DartifactId=libthrift -Dversion=0.9.2 -Dpackaging=jar

注意

maven的版本也需要注意,我一开始使用的是3.5.4的版本,结果安装失败

http://blogimgbucketxun.oss-cn-beijing.aliyuncs.com/xiaoYiXun/common/20200822_16383779.png

后来我换成了3.6.1版本就成功了

http://blogimgbucketxun.oss-cn-beijing.aliyuncs.com/xiaoYiXun/common/20200822_16383745.png

个人感觉可能是我3.5.4的maven有什么地方有损坏,所以才导致的不成功。所以如果一直不成功,可以试着换个新的版本

全部代码:

package com.ttxn.modules.oss.controller;


import com.lowagie.text.pdf.PdfReader;
import com.ttxn.common.config.DataSourceNames;
import com.ttxn.common.data.DataSource;
import com.ttxn.common.util.Base64DecodeMultipartFile;
import com.ttxn.common.util.JsonUtils;
import com.ttxn.modules.oss.entity.SysFile;
import com.ttxn.modules.oss.manage.FileManageFactory;
import com.ttxn.modules.oss.service.ISysFileService;
import com.ttxn.modules.oss.service.impl.SysFileServiceImpl;
import com.ttxn.modules.oss.vo.OssSetting;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.builder.BuilderException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.model.TextRun;
import org.apache.poi.hslf.usermodel.RichTextRun;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.xslf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

/**
 * @author Bigsightx
 */
@Slf4j
@RestController
@Api(description = "文件上传接口")
@RequestMapping("/sysFile/upload")

public class UploadController {

    @Autowired
    PdfOperation pdfOperation;

    @Autowired
    private FileManageFactory fileManageFactory;

    @Autowired
    private ISysFileService fileService;

    @Autowired
    private OssSetting ossSetting;

    @Value("${myapp.path.upload}")
    private String uploadPath;


    //    @ApiOperation(value = "PPT文件转图片上传")
//    @PostMapping("/ppt2ImageUpload")
    public String doPPTtoImage(MultipartFile file) {
//        return null
//        filePath = "F:\\PPT.pptx";
//        File file = new File(filePath);
        String fileName = file.getOriginalFilename();
        String fileSuffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());
        String localFileName = System.currentTimeMillis() + fileSuffix;
        String filePath = uploadPath + File.separator + localFileName;
        File localFile = new File(filePath);
        try {
            file.transferTo(localFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        File file1 = new File(filePath);
        return convertPPTtoImage(file1);
    }


    public String convertPPTtoImage(File file) {
        //先将PPT转成PDF
        String path = pdfOperation.convertPDF(file, uploadPath);

        if (StringUtils.isNotBlank(path)) {
            List<SysFile> sysList = new ArrayList<>();
            try {
                File pdfFile = new File(path);

                uploadPDF(path, sysList, pdfFile);

            } catch (IOException e) {
                e.printStackTrace();
            }
            return JsonUtils.serialize(sysList);
        }
        return null;
    }

    public static int checkFile(File file) {
        int isppt = -1;
        String filename = file.getName();
        String suffixname = null;
        if (filename != null && filename.indexOf(".") != -1) {
            suffixname = filename.substring(filename.indexOf("."));
            if (suffixname.equals(".ppt")) {
                isppt = 0;
            } else if (suffixname.equals(".pptx")) {
                isppt = 1;
            }
        }
        return isppt;
    }


    @ApiOperation("课件上传")
    @PostMapping("/uploadCourseware")
    @DataSource(DataSourceNames.TTXN_SAAS_SYS)
    public String uploadCourseware(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        String suffixname = fileName.substring(fileName.lastIndexOf("."));
        if (suffixname.endsWith(".ppt") || suffixname.endsWith(".pptx")) {
            return doPPTtoImage(file);
        } else if (suffixname.endsWith(".pdf")) {
            return pdf2Image(file);
        }
        return null;
    }


    //    @ApiOperation(value = "PDF文件转图片上传")
//    @PostMapping("/pdf2ImageUpload")
    public String pdf2Image(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        String fileSuffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());
        String localFileName = System.currentTimeMillis() + fileSuffix;
        String filePath = uploadPath + File.separator + localFileName;
        File localFile = new File(filePath);
        try {
            file.transferTo(localFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<SysFile> sysList = new ArrayList<>();
        try {
            File pdfFile = new File(filePath);

            uploadPDF(filePath, sysList, pdfFile);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return JsonUtils.serialize(sysList);
    }

    private void uploadPDF(String filePath, List<SysFile> sysList, File pdfFile) throws IOException {
        PDDocument pdDocument;
        int dot = pdfFile.getName().lastIndexOf('.');
        String imagePDFName = pdfFile.getName().substring(0, dot); // 获取图片文件名
        String imgFolderPath = null;


        pdDocument = PDDocument.load(pdfFile);
        PDFRenderer renderer = new PDFRenderer(pdDocument);
        /* dpi越大转换后越清晰,相对转换速度越慢 */
        PdfReader reader = new PdfReader(filePath);
        int pages = reader.getNumberOfPages();
        StringBuffer imgFilePath = null;
        for (int i = 0; i < pages; i++) {
            String imgFilePathPrefix = imgFolderPath + pdfFile.separator + imagePDFName;
            imgFilePath = new StringBuffer();
            imgFilePath.append(imgFilePathPrefix);
            imgFilePath.append("_");
            imgFilePath.append(String.valueOf(i + 1));
            imgFilePath.append(".png");
            BufferedImage image = renderer.renderImageWithDPI(i, 300);


            SysFile f = getSysFile(i, image);
            sysList.add(f);
        }
    }

    public SysFile getSysFile(int i, BufferedImage image) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
        ImageIO.write(image, "png", baos);
        byte[] bytes = baos.toByteArray();//转换成字节
        BASE64Encoder encoder = new BASE64Encoder();
        String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
        png_base64 = "data:image/jpg;base64," + png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
        System.out.println("值为:" + "data:image/jpg;base64," + png_base64);

        MultipartFile multipartFile = Base64DecodeMultipartFile.base64Convert(png_base64);
        String result = "";
        String fKey = renamePic(multipartFile.getOriginalFilename());
        SysFile f = new SysFile();
        InputStream inputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 上传至第三方云服务或服务器
        result = fileManageFactory.getFileManage(null).inputStreamUpload(inputStream, fKey, multipartFile);
        f.setLocation(2);
        // 保存数据信息至数据库
        f.setName(i + multipartFile.getOriginalFilename());
        f.setSize(multipartFile.getSize());
        f.setType(multipartFile.getContentType());
        f.setFKey(fKey);
        f.setUrl(result);
        fileService.save(f);
        return f;
    }

    @ApiOperation(value = "文件上传")
    @PostMapping(value = "/file")
    @DataSource(DataSourceNames.TTXN_SAAS_SYS)
    public SysFile upload(HttpServletRequest request, @RequestParam(required = false) String base64, @RequestParam(required = false) MultipartFile file) throws IOException {
        if (!ossSetting.getEnabled()) {
            throw new BuilderException("未开启文件上传");
        }


        if (ossSetting.getType().equals("1")) {
            return localUpload(request, file);
        } else if (ossSetting.getType().equals("2")) {
            return aliUpload(request, base64, file);
        }
        return null;
    }

    @PostMapping("/twoCodeUpload")
    public SysFile twoCodeUpload(HttpServletRequest request, String filePath) {
        try {
            File file = new File(filePath);
            InputStream inputStream = new FileInputStream(file);
            MultipartFile multipartFile = new MockMultipartFile(file.getName(), inputStream);
            return aliUpload(request, null, multipartFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public SysFile localUpload(HttpServletRequest request, MultipartFile mf) throws IOException {
        String ctxPath = uploadPath;
        String fileName = null;
        String bizPath = "user";
        if (request.getParameter("basePath") != null) {
            bizPath = request.getParameter("basePath");
        }
        String nowday = new SimpleDateFormat("yyyyMMdd").format(new Date());
        File file = new File(ctxPath + File.separator + bizPath + File.separator + nowday);
        if (!file.exists()) {
            file.mkdirs();// 创建文件根目录
        }
        String orgName = mf.getOriginalFilename();// 获取文件名
        fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
        String savePath = file.getPath() + File.separator + fileName;
        File savefile = new File(savePath);
        FileCopyUtils.copy(mf.getBytes(), savefile);
        String dbpath = bizPath + File.separator + nowday + File.separator + fileName;
        if (dbpath.contains("\\")) {
            dbpath = dbpath.replace("\\", "/");
        }
        SysFile f = new SysFile();
        f.setLocation(1);
        // 保存数据信息至数据库
        f.setName(orgName);
        f.setSize(savefile.length());
        f.setType(mf.getContentType());
        f.setFKey(fileName);
        f.setUrl(dbpath);
        fileService.save(f);
        return f;
    }

    public SysFile aliUpload(HttpServletRequest request, String base64, MultipartFile file) throws IOException {
        String resultUrl = "";
        if (null != base64 && base64 != "") {
            // base64上传
            file = Base64DecodeMultipartFile.base64Convert(base64);
        }

        String fKey = null;
        if (StringUtils.isNotBlank(file.getOriginalFilename())) {
            fKey = renamePic(file.getOriginalFilename());
        } else {
            fKey = renamePic(file.getName());
        }
        String bizPath = request.getParameter("basePath");
        if (bizPath != null) {
            fKey = bizPath + "/" + fKey;
        }
        SysFile f = new SysFile();
        InputStream inputStream = file.getInputStream();
        // 上传至第三方云服务或服务器
        resultUrl = fileManageFactory.getFileManage(null).inputStreamUpload(inputStream, fKey, file);
        f.setLocation(2);
        // 保存数据信息至数据库
        f.setName(file.getOriginalFilename());
        f.setSize(file.getSize());
        f.setType(file.getContentType());
        f.setFKey(fKey);
        f.setUrl(resultUrl);
        fileService.save(f);
        return f;
    }

    /**
     * 以UUID重命名
     *
     * @param fileName
     * @return
     */
    public static String renamePic(String fileName) {
        String extName = fileName.substring(fileName.lastIndexOf("."));
        return UUID.randomUUID().toString().replace("-", "") + extName;
    }


}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值