Java调用shell脚本执行imagemagick压缩图片
程序员文章站
2022-09-14 09:03:09
文章目录前言安装方式一:Dockerfile方式二:进入已有容器内部安装测试Linux上压缩Java执行shell实现压缩前言自己做个小项目,有个需求得存储图片,为了页面渲染速度。这里存储的是压缩图片,然后外链指向原图。本地不存储。美滋滋。但是想法很美好,结果缺不尽人意…业务逻辑上一点问题没有,结果出在服务器上,内存不足,导致宕机。一通排查之后发现是压缩图片这里导致的内存溢出。尝试解决办法:所有IO流操作完立马close,无效数量降低为每分钟处理3张图片,无效采用谷歌的开源工具th....
前言
自己做个小项目,有个需求得存储图片,为了页面渲染速度。
这里存储的是压缩图片,然后外链指向原图。本地不存储。美滋滋。
但是想法很美好,结果缺不尽人意…
业务逻辑上一点问题没有,结果出在服务器上,内存不足,导致宕机。
一通排查之后发现是压缩图片这里导致的内存溢出。
尝试解决办法:
- 所有IO流操作完立马close,无效
- 数量降低为每分钟处理3张图片,无效
- 采用谷歌的开源工具thumbnailator,无效
最后无奈在linux上安装imagemagick,然后java执行shell语句去压缩图片。
然后就一路顺畅了,不得不说java的IO真的吃内存。
安装
介绍一下本文的环境,java项目运行在docker容器中,基于java:8-alpine镜像。
注意是alpine,超苗条的linux。所以很多基本指令在容器内都没有。
方式一:Dockerfile
全写注释了,就不做过多额外的解释了
FROM java:8-alpine
ADD target/xxx.jar xxx.jar
# 修改alpine的源地址改为阿里的,否则下载速度极慢
RUN echo -e "https://mirrors.aliyun.com/alpine/v3.7/main" > /etc/apk/repositories
# 更新本地apk的镜像索引数据 并且 安装imagemagick
RUN apk update && apk add imagemagick
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/xxx.jar"]
方式二:进入已有容器内部安装
# 进入容器,因为是基于alpine,所以这里用sh,而不是bash
docker exec -it xxx sh
# 修改alpine的源地址改为阿里的,否则下载速度极慢
echo -e "https://mirrors.aliyun.com/alpine/v3.7/main" > /etc/apk/repositories
# 更新本地apk的镜像索引数据 并且 安装imagemagick
apk update && apk add imagemagick
测试
convert -version
/ # convert -version
Version: ImageMagick 7.0.7-11 Q16 x86_64 2017-11-15 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP
Delegates (built-in): bzlib cairo fontconfig freetype gslib jng jpeg lcms ltdl pangocairo png ps rsvg tiff webp xml zlib
/ #
Linux上压缩
官方示例:https://www.imagemagick.org/Usage/
# 压缩质量为70% 1.png:源文件 to1.jpng:压缩后的文件
convert -quality 70% 1.png to1.jpg && rm -f 1.png
# 如何用这个还是提示内存不足的话,再加上两个参数即可。设置最大内存2mb
convert -limit memory 2mb -limit map 2mb -quality 70% 1.png to1.jpg && rm -f 1.png
Java执行shell实现压缩
String cmd = "convert -limit memory 2mb -limit map 2mb -quality 70% 1.png to1.jpg && rm -f 1.png";
// "sh", "-c"不可省略,waitFor:阻塞线程等待shell执行结束
Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd}).waitFor();
本文地址:https://blog.csdn.net/wkh___/article/details/107144869