将图片压缩至指定大小Kb(Thumbnailator)

放代码前,先唠叨唠叨,舒缓一下我的郁闷之情。

今天下午改一个后台管理系统的需求,要求上传的图片要压缩到300kb,感觉不难,就开搞。

先撩拨一下度娘,搞点货出来瞅瞅,不复杂就干脆搬砖算了。

嗯,度娘不愧为度娘,货不少,找到一个简单(优秀)的一匹的博文,用的是一个优秀的google开源的图片处理的java类库Thumbnailator(想了解么,有大神总结了[Thumbnailator使用简介],和前面那篇差不多,呵呵)。

不过呢,他们只是介绍了这个优秀的类库的使用,而我需要指定将图片压缩到多大,所以说呢,度娘真美,要啥给啥[使用Thumbnails实现图片指定大小压缩],美滋滋,开始搬砖,搬完还要搞其他的事呢。

燃,冰卵,由于开发框架用的是闲大赋团队开发的SpringBoot-Plus的后台管理系统,他的图片上传后,会在图片名称后加上UUID,这就导致了,使用Thumbnailator中的方法输出文件时,会报net.coobird.thumbnailator.tasks.UnsupportedFormatException: No suitable ImageReader found for source data.-找不到合适的图片阅读器的异常,因为后缀不在是图片的后缀了,而是一串UUID。无奈的我,只能想办法解决咯。

幸运的是,有大佬[java图片压缩(Thumbnails)]在,我站上了巨人的肩膀,哈哈哈

好了,不逼逼了,放上代码,记录一下:

SpringBoot-Plus的图片上传方法,略作修改:
/*附件类操作*/
@PostMapping(MODEL + "/uploadAttachment.json")
@ResponseBody
public JsonResult uploadFile(@RequestParam("file") MultipartFile file,String batchFileUUID,String bizType,String bizId) throws IOException {
    if(file.isEmpty()) {
        return JsonResult.fail();
    }
    System.out.println(batchFileUUID + "========= type =========   "  + bizType + "   "  + bizId  );
    CoreUser user = platformService.getCurrentUser();
    CoreOrg  org = platformService.getCurrentOrg();
    FileItem fileItem = fileService.createFileItem(file.getOriginalFilename(), bizType, bizId, user.getId(), org.getId(), batchFileUUID,null);
    saveAttachment(file,batchFileUUID,bizId,user,fileItem);
    OutputStream os = fileItem.openOutpuStream();
    // 添加判断,上传的文件是否是图片
    if("jpg|png|gif|bmp|jpeg".contains(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1))){
    	// 使用压缩方法
        byte[] bytes = FileUtil.commpressPicCycle(file.getBytes(), 300, 0.5f);
        os.write(bytes);
        os.close();
    }else {
        FileUtil.copy(file.getInputStream(), os);
    }
    return JsonResult.success(fileItem);
}
压缩方法:
/**
     *
     * @param bytes 原图片字节数组
     * @param desFileSize 指定图片大小,单位 kb
     * @param accuracy 精度,递归压缩的比率,建议小于0.9
     * @return
     */
    public static byte[] commpressPicCycle(byte[] bytes, long desFileSize, double accuracy) throws IOException{
        // 获取目标图片
//        File imgFile = new File(desPath);
//        long fileSize = imgFile.length();
        long fileSize = bytes.length;
        System.out.println("=====fileSize======== "+fileSize);
        // 判断图片大小是否小于指定图片大小
        if(fileSize <= desFileSize * 1024){
            return bytes;
        }
        //计算宽高
        BufferedImage bim = ImageIO.read(new ByteArrayInputStream(bytes));
        int imgWidth = bim.getWidth();
        System.out.println(imgWidth+"====imgWidth=====");
        int imgHeight = bim.getHeight();
        int desWidth = new BigDecimal(imgWidth).multiply( new BigDecimal(accuracy)).intValue();
        System.out.println(desWidth+"====desWidth=====");
        int desHeight = new BigDecimal(imgHeight).multiply( new BigDecimal(accuracy)).intValue();
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流(写入到内存)
        Thumbnails.of(new ByteArrayInputStream(bytes)).size(desWidth, desHeight).outputQuality(accuracy).toOutputStream(baos);
        //如果不满足要求,递归直至满足要求
        return commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);
    }

好了,记录完成。

posted @ 2019-12-19 21:49  IT-小浣熊  阅读(722)  评论(0)    收藏  举报