kkFileview代码分析(十一)——文件转换相关

2021SC@SDUSC

目录

消费队列中的转换文件FileConvertQueueTask

1、初始化方法:

2、startTask方法:开启队列 

3、队列运行分析

4、判断是否需要转换

文件处理服务类FileHandlerService

 1、获取已经转换过的文件集合

 2、路径转换

3、路径提取

4、解压压缩包图片文件

5、添加缓存 

 6、对转换后的文件进行操作

7、获取文件属性


消费队列中的转换文件FileConvertQueueTask

FileConvertQueueTask是该项目层中的业务组件,因为其被@service注解标记。

1、初始化方法:

初始类中的previewFactory、cacheservice和filehandlerservice对象。

    public FileConvertQueueTask(FilePreviewFactory previewFactory, CacheService cacheService, FileHandlerService fileHandlerService) {
        this.previewFactory = previewFactory;
        this.cacheService = cacheService;
        this.fileHandlerService = fileHandlerService;
    }

2、startTask方法:开启队列 

        @PostConstruct是Java自己的注解,被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行。

        在这个方法中,启动线程,在线程里实例化一个ConverterTask存放处理文件转换的队列,这样全局的转换文件就可以存放到队列中。队列中包含的对象有previewFactory、cacheService、fileHandlerService。

    @PostConstruct
    public void startTask() {
        new Thread(new ConvertTask(previewFactory, cacheService, fileHandlerService))
                .start();
        logger.info("队列处理文件转换任务启动完成 ");
    }

        ConverterTask类

    static class ConvertTask implements Runnable {

        private final Logger logger = LoggerFactory.getLogger(ConvertTask.class);
        private final FilePreviewFactory previewFactory;
        private final CacheService cacheService;
        private final FileHandlerService fileHandlerService;

        public ConvertTask(FilePreviewFactory previewFactory,
                           CacheService cacheService,
                           FileHandlerService fileHandlerService) {
            this.previewFactory = previewFactory;
            this.cacheService = cacheService;
            this.fileHandlerService = fileHandlerService;
        }

 

3、队列运行分析

        当队列中存入url时,首先分析要转换文件的初始类型,之后才可以选择合适的处理方法。首先实例化FileAttribute对象fileAttribute,通过调用fileHandlerService的方法getFileAttribute(url, null)获取;实例化 FileType 对象fileType,通过调用fileAttribute的getType()方法,这样获取文件类型就完成。(FileAttribute的方法在之前有分析。)

        之后通过调用isNeedConvert(fileType)分析文件是否需要转换,如果需要处理调用 FilePreview对象filePreview,该对象通过调用previewFactory.get(fileAttribute)方法获取,之后调用filePreview.filePreviewHandle(url, new ExtendedModelMap(), fileAttribute)方法对预制文件进行处理。

        如果中途线程出现问题,先尝试Sleep,如果sleep出现异常,中断当前线程并报错。

        @Override
        public void run() {
            while (true) {
                String url = null;
                try {
                    url = cacheService.takeQueueTask();
                    if (url != null) {
                        FileAttribute fileAttribute = fileHandlerService.getFileAttribute(url, null);
                        FileType fileType = fileAttribute.getType();
                        logger.info("正在处理预览转换任务,url:{},预览类型:{}", url, fileType);
                        if (isNeedConvert(fileType)) {
                            FilePreview filePreview = previewFactory.get(fileAttribute);
                            filePreview.filePreviewHandle(url, new ExtendedModelMap(), fileAttribute);
                        } else {
                            logger.info("预览类型无需处理,url:{},预览类型:{}", url, fileType);
                        }
                    }
                } catch (Exception e) {
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    } catch (Exception ex) {
                        Thread.currentThread().interrupt();
                        ex.printStackTrace();
                    }
                    logger.info("处理预览转换任务异常,url:{}", url, e);
                }
            }
        }

4、判断是否需要转换

        如果filetype中含有"compress"、"office"、"cad"这三个字符串,则判定是需要处理的文件,将true传回给调用函数,之后即可用FilePreview进行处理。


        public boolean isNeedConvert(FileType fileType) {
            return fileType.equals(FileType.COMPRESS) || 
                fileType.equals(FileType.OFFICE) || 
                fileType.equals(FileType.CAD);
        }

 

文件处理服务类FileHandlerService

        这个类之前在介绍pdf文件转换的时候有提到,这里面有pdf转图片的方法,也有cad文件转pdf的方法。但是这个类中封装了一些在文件转换中重复度比较高的代码,比如存放文件缓存、获取文件路径、转换路径等相关问题。在下文将进行详细介绍。

 1、获取已经转换过的文件集合

由于文件类型不贴心,获取文件缓存的方式也不同。主要有以下几种:

一种是调用cacheService的getPDFCache获取转换过的pdf文件缓存

   /**
     * @return 已转换过的文件集合(缓存)
     */
    public Map<String, String> listConvertedFiles() {
        return cacheService.getPDFCache();
    }

一种是 根据文件名获取文件集合

    /**
     * @return 已转换过的文件,根据文件名获取
     */
    public String getConvertedFile(String key) {
        return cacheService.getPDFCache(key);
    }

获取视频文件集合 

    /**
     * @return 已转换过的视频文件集合(缓存)
     */
    public Map<String, String> listConvertedMedias() {
        return cacheService.getMediaConvertCache();
    }
    /**
     * 添加转换后的视频文件缓存
     * @param fileName
     * @param value
     */
    public void addConvertedMedias(String fileName, String value) {
        cacheService.putMediaConvertCache(fileName, value);
    }
    /**
     * @return 已转换视频文件缓存,根据文件名获取
     */
    public String getConvertedMedias(String key) {
        return cacheService.getMediaConvertCache(key);
    }

 

 2、路径转换

调用cacheService的getPdfImageCache方法,根据pdf本地路径转换成生成图片的本地相对路径,该方法在pdf2jpg中有调用。

    /**
     * @param key pdf本地路径
     * @return 已将pdf转换成图片的图片本地相对路径
     */
    public Integer getConvertedPdfImage(String key) {
        return cacheService.getPdfImageCache(key);
    }

3、路径提取

通过分割路径path的字符串获取文件名。

    /**
     * 从路径中获取文件名
     *
     * @param path 类似这种:C:\Users\yudian-it\Downloads
     * @return 文件名
     */
    public String getFileNameFromPath(String path) {
        return path.substring(path.lastIndexOf(File.separator) + 1);
    }

 绝对路径->相对路径

通过对绝对路径字符串分割获取相对路径

    /**
     * 获取相对路径
     *
     * @param absolutePath 绝对路径
     * @return 相对路径
     */
    public String getRelativePath(String absolutePath) {
        return absolutePath.substring(fileDir.length());
    }

4、解压压缩包图片文件

调用cacheservice的方法getImgCache,获取图片 以及putImgCache将图片添加至压缩包。

    /**
     * 获取redis中压缩包内图片文件
     *
     * @param fileKey fileKey
     * @return 图片文件访问url列表
     */
    public List<String> getImgCache(String fileKey) {
        return cacheService.getImgCache(fileKey);
    }

    /**
     * 设置redis中压缩包内图片文件
     *
     * @param fileKey fileKey
     * @param imgs    图片文件访问url列表
     */
    public void putImgCache(String fileKey, List<String> imgs) {
        cacheService.putImgCache(fileKey, imgs);
    }

5、添加缓存 

根据缓存的类型不同分为pdf缓存和pdf图片缓存。

    /**
     * 添加转换后PDF缓存
     *
     * @param fileName pdf文件名
     * @param value    缓存相对路径
     */
    public void addConvertedFile(String fileName, String value) {
        cacheService.putPDFCache(fileName, value);
    }

    /**
     * 添加转换后图片组缓存
     *
     * @param pdfFilePath pdf文件绝对路径
     * @param num         图片张数
     */
    public void addConvertedPdfImage(String pdfFilePath, int num) {
        cacheService.putPdfImageCache(pdfFilePath, num);
    }

 6、对转换后的文件进行操作

这个方法主要用于改变编码格式,首先声明对象StringBuilder,之后选择编码方式gb2312或者是utf-8,之后添加sheet控制头。全部完成之后生成FileOutputStream文件输出流,将文件都写入参数outfilepath中。


    public void doActionConvertedFile(String outFilePath) {
        StringBuilder sb = new StringBuilder();
        try (InputStream inputStream = new FileInputStream(outFilePath);
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, DEFAULT_CONVERTER_CHARSET))) {
            String line;
            while (null != (line = reader.readLine())) {
                if (line.contains("charset=gb2312")) {
                    line = line.replace("charset=gb2312", "charset=utf-8");
                }
                sb.append(line);
            }
            // 添加sheet控制头
            sb.append("<script src=\"js/jquery-3.0.0.min.js\" type=\"text/javascript\"></script>");
            sb.append("<script src=\"js/excel.header.js\" type=\"text/javascript\"></script>");
            sb.append("<link rel=\"stylesheet\" href=\"bootstrap/css/bootstrap.min.css\">");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 重新写入文件
        try (FileOutputStream fos = new FileOutputStream(outFilePath);
             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8))) {
            writer.write(sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

7、获取文件属性

    public FileAttribute getFileAttribute(String url, HttpServletRequest req) {
        FileAttribute attribute = new FileAttribute();
        String suffix;
        FileType type;
        String fileName;
        String fullFileName = WebUtils.getUrlParameterReg(url, "fullfilename");
        if (StringUtils.hasText(fullFileName)) {
            fileName = fullFileName;
            type = FileType.typeFromFileName(fullFileName);
            suffix = KkFileUtils.suffixFromFileName(fullFileName);
        } else {
            fileName = WebUtils.getFileNameFromURL(url);
            type = FileType.typeFromUrl(url);
            suffix = WebUtils.suffixFromUrl(url);
        }
        attribute.setType(type);
        attribute.setName(fileName);
        attribute.setSuffix(suffix);
        attribute.setUrl(url);
        if (req != null) {
            String officePreviewType = req.getParameter("officePreviewType");
            String fileKey = WebUtils.getUrlParameterReg(url,"fileKey");
            if (StringUtils.hasText(officePreviewType)) {
                attribute.setOfficePreviewType(officePreviewType);
            }
            if (StringUtils.hasText(fileKey)) {
                attribute.setFileKey(fileKey);
            }
        }
        return attribute;
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值