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

前 言

一位亲戚,在事业单位工作很多年了,最近准备申请高级工程师的职称,但是审核材料的网站,上传的图片必须为 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;
    }

通过这一步,就将所有的 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);
            }
        }
    }

总结

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

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值