• 我用代码帮亲戚处理了评职称的材料问题,顿时觉得写代码还是挺香的


    前 言

    一位亲戚,在事业单位工作很多年了,最近准备申请高级工程师的职称,但是审核材料的网站,上传的图片必须为 jpg 格式且大小不能超过 512kb ,于是找到我帮忙。

    我一想,直接回复,很简单啊,用很多 app 或者截图保存的时候,改一下后缀就行了,我帮你搞定。

    结果,对方直接发过来一个差不多 500M 的压缩包,把我人看傻眼了,不是只有一点点吗?怎么这么多?!

    我解压后瞅了一眼,最外层1个压缩包,里面有31个压缩包,每个压缩包下,又有各自的多个文件夹或者图片,更多的是 pdf 文档。

    亲戚告诉我,这是她收集了差不多两个月的所有材料了,需要全部搞成 jpg 图片且图片大小不能超过 512kb。

    好家伙,我答应得太爽快了,这下掉大坑里了!

    如果按上面说到这种做法,手动用 app 或者截图的方式去搞,得搞到猴年马月,怕是提交审核的时间都耽误了。

    这要是放在我还没参加工作或者刚参加工作没多久那会儿,我估计就不要脸地拒绝回去了!不过现在信誓旦旦地答应了下来,总不能怂了,得想办法搞一搞。

    有了这种想法,这时候,我就拿这东西,当作一个需求来处理了,转身进入开发者模式。

    需求分析

    作为开发者,拿到一个需求,第一步不是想着怎么写代码,而是做好一个需求分析,明确具体要求是什么,要达到什么样的目标,有哪些可以利用的资源等待。

    我再三和亲戚确认,得到了以下较为清晰的信息:

    1. 要 jpg 图片
    2. 所有图片大小不超过 512 kb
    3. 只有这一个接近 500 M 的压缩包,没有别的了
    4. 交付时间最迟是 4 天后
    5. 如果是 pdf 文档就拆分成 jpg 图片,如果已经是图片的,就压缩图片大小,限制在 512 kb以下,但是不改变图片的尺寸大小。

    综合所有信息,我发现我就需要做两个事:

    • 一个是把所有 pdf 文件拆分成 jpg 图片
    • 另外一个就是压缩图片大小

    看到东西不复杂,我松了口气,不过也不算太轻松,因为这东西,量太多。

    写代码处理文档,解决问题

    总共两步走,第一步就是将所有 pdf 文档拆分成 jpg 图片;第二部就是将所有超过 512kb 的图片,进行压缩。

    将pdf文档拆分成jpg图片

    这里给出主要的是实现方法,由于涉及多个文件夹且多个 pdf 文档,所以在写测试方法时,是需要根据实际情况,加上 for 循环调用的。

    /**
         * 将PDF文档拆分成多张图片,并返回所有图片的路径
         *
         * @param pdfPath
         * @param pictureFolderPath
         * @return
         * @throws Exception
         */
        public static List<String> pdfSwitchToPicture(String pdfPath, String pictureFolderPath) throws Exception {
            List<String> picUrlList = new ArrayList<>();
            File file = new File(pictureFolderPath);
            if (!file.exists()) {
                file.mkdirs();
            }
            String pictureRootName = file.getName() + "_";
            List<byte[]> imageList = handlePdf(pdfPath);
            AtomicInteger pictureNameNumber = new AtomicInteger(1);
            for (byte[] image : imageList) {
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                byteArrayOutputStream.write(image);
                String pictureUrl = file.getAbsolutePath() + File.separator + pictureRootName + pictureNameNumber.getAndIncrement() + ".jpg";
                byteArrayOutputStream.writeTo(new FileOutputStream(pictureUrl));
                picUrlList.add(pictureUrl);
                byteArrayOutputStream.close();
            }
            return picUrlList;
        }
    
        /**
         * 处理PDF文档
         *
         * @param pdfPath
         * @return
         * @throws Exception
         */
        public static List<byte[]> handlePdf(String pdfPath) throws Exception {
            File pdfFile = new File(pdfPath);
            //加载PDF文档
            PDDocument pdDocument = PDDocument.load(pdfFile);
            //创建PDF渲染器
            PDFRenderer pdfRenderer = new PDFRenderer(pdDocument);
            int pageNum = pdDocument.getNumberOfPages();
            List<byte[]> list = new ArrayList<>();
            for (int i = 0; i < pageNum; i++) {
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                //将PDF的每一页渲染成一张图片,并放大1.5倍
                BufferedImage image = pdfRenderer.renderImage(i, 1.5F);
                ImageIO.write(image, "jpg", outputStream);
                list.add(outputStream.toByteArray());
                outputStream.close();
            }
            pdDocument.close();
            return list;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    通过这一步,就将所有的 pdf 文档拆分成图片了,接下来就是压缩。

    压缩图片

    有一部分图片是 pdf 文档拆分出来就超过 512kb 的,有一部分是直接用手机拍摄的,动不动就是好几 M 大小,但又有一些事符合要求的。

    因此在处理时,需要加好判断条件,别搞错了。同样的,由于涉及多个文件夹,所以在测试方法中,一样需要增加 for 调用处理的方法。

    下面是主要的压缩方法,其余的需要根据具体的业务场景,自己定制化开发。

    /**
         * 根据指定大小压缩图片
         *
         * @param imageBytes     原图片字节数组大小
         * @param targetFileSize 要压缩的大小
         * @param picturePath    图片绝对路径
         */
        public static void compressPicForScale(byte[] imageBytes, long targetFileSize, String picturePath) {
    
            long srcSize = imageBytes.length;
            if (srcSize > targetFileSize * 1024) {
                log.info("当前压缩的图片是:{}", picturePath);
                File file = new File(picturePath);
                long tempSize = srcSize;
                double accuracy = getAccuracy(srcSize / 1024);
                try {
                    while (tempSize > targetFileSize * 1024) {
                        ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                        FileOutputStream fileOutputStream = new FileOutputStream(file);
                        Thumbnails.of(inputStream)
                                .scale(accuracy)
                                .outputQuality(accuracy)
                                .toOutputStream(fileOutputStream);
                        tempSize = file.length();
                    }
                } catch (Exception e) {
                    log.error("====压缩图片失败====", e);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    总结

    下班回来后,花了一个晚上的时间,帮她解决了这个事,压缩成一个 100 多 M 的包交付给她。

    她收到并查看,然后露出了一个长辈对晚辈满意的微笑,然后没然后了,只有我在风中凌乱…

    这个事,难度不大,就是想清楚逻辑,然后动手就行。

    不过能这么快解决,我第一次觉得,写代码还是有点意思的,解决起这种重复性这么高的问题来,还挺香,点个运行,就不用管了,如果有点小问题就多运行两次调试一下 ,省时省事!

  • 相关阅读:
    HashData获得华为鲲鹏Validated认证 信创版图持续壮大
    Java从萌新小白到顶级大牛(7更新中)
    【SSM】SpringMVC系列——SpringMVC注解式开发
    电容容量换算电池容量,以及RTC持续时间计算
    5、Spring之Bean生命周期源码解析(销毁)
    二维数组转化为普通数组
    INTERSPEECH 2022|FS-CANet: 基于全带子带交叉注意力机制的语音增强
    深入理解Java NIO:原理、应用与实战详解
    Mining Association Rules between Sets of Items in Large Databases
    Centos7,yum安装mysql
  • 原文地址:https://blog.csdn.net/Crezfikbd/article/details/126098309