Skip to content

Instantly share code, notes, and snippets.

@hushi55
Created October 30, 2015 06:42
Show Gist options
  • Select an option

  • Save hushi55/26541e9403a3df40ca53 to your computer and use it in GitHub Desktop.

Select an option

Save hushi55/26541e9403a3df40ca53 to your computer and use it in GitHub Desktop.
Java 使用 gm 压缩图片
public class Im4javaUtil implements ImageUtil {
private static final Logger logger = LoggerFactory.getLogger(Im4javaUtil.class);
private static String tmpdir;
private static boolean WINDOW_OS = false;
static {
String osName = System.getProperty("os.name").toLowerCase();
WINDOW_OS = osName.indexOf("win") != -1;
}
@Autowired
private FileService fileService;
@Resource(name="JavaImageUtil")
private JavaImageUtil javaImageUtil;
@Value("${ImageServiceImpl.graphics.magick.gif2jpg}")
private boolean gif2jpg = false;
/**
* 裁剪图片
*/
@Override
public String transImage(final String id, int width, int hight, int x, int y, int rotate) throws IOException {
DocumentInfo imageDocInfo = fileService.findById(id);
if(imageDocInfo == null) {
throw new IOException("Image["+id+"] not found!");
}
File desc = this.getDesc(imageDocInfo);
File soruce = this.getSource(imageDocInfo);
InputStream tempFileInputStream = null;
try {
String cmd = MessageFormat.format("gm convert -crop {0, number,#}x{1, number,#}+{2, number,#}+{3, number,#} -rotate {4, number,#} {5} {6} ",
width, hight, x, y,
rotate,
soruce.getAbsolutePath(),
desc.getAbsolutePath());
this.runCommand(cmd);
FileMetadata metadata = new MongoFileMetadata();
metadata.put("filename", desc.getName());
metadata.put("original_image_id", id);
// 保存到mongodb
MongoFAO mfao = (MongoFAO) FAOFactory.getInstance();
tempFileInputStream = new FileInputStream(desc);
return mfao.saveFile(tempFileInputStream, metadata);
} catch (Exception e) {
String message = " image id: " + id + ". " + e.getMessage();
logger.warn(message, e);
/**
* copy 出错文件到到一个文件夹
*/
File debug = new File("/kingdee/debug/uploadimage/");
if (debug.exists() && debug.isDirectory()) {
try {
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File debugdir = new File(debug.getAbsolutePath() + "/" + date);
if (!debugdir.exists() && debugdir.mkdirs()) {
this.runCommand(" cp " + soruce.getAbsolutePath() + " " + debugdir.getAbsolutePath() );
logger.info("copy " + soruce.getAbsolutePath() + " to " + debugdir.getAbsolutePath());
}
} catch (Exception e1) {
logger.warn(message, e);
}
}
throw new RuntimeException(message, e);
} finally {
IOUtils.closeQuietly(tempFileInputStream);
if (soruce.exists()) {
soruce.delete();
}
if (desc.exists()) {
desc.delete();
}
}
}
@Override
public String resizeImage(final String imageId, int width, int height) throws IOException {
DocumentInfo imageDocInfo = fileService.findById(imageId);
if(imageDocInfo == null) {
throw new IOException("Image["+imageId+"] not found!");
}
File desc = this.getDesc(imageDocInfo);
File soruce = this.getSource(imageDocInfo);
InputStream tempFileInputStream = null;
try {
/**
* http://blog.ddtet.org/2014/03/graphicsmagick.html
*
* gm convert -auto-orient -strip [圖片檔名] [輸出圖片檔名]
*
* convert -resize "500x300>" input.jpg output.jpg #如果图片比500x300小就保持原样,以防小图片被放大失真。
*
*
*
* http://blog.chinaunix.net/uid-20691565-id-3546380.html
*
* 8.使用^命令后缀可以使用宽高中较小的那个值作为尺寸
如:convert -resize “300×300^” src.jpg dst.jpg
此命令执行后,dst.jpg图片大小为(400×300),图片保持原有比例,(300:300 < 200:150,选择高作为最小尺寸)。
如:convert -resize “300×200^” src.jpg dst.jpg
此命令执行后,dst.jpg图片大小为(300×225),图片保持原有比例,(300:200 > 200:150,选择宽作为最小尺寸)
*/
String pic_src = soruce.getAbsolutePath();
String pic_desc = desc.getAbsolutePath();
/**
* -auto-orient 自动将图片旋转为正方向
* -strip 去除掉多余的信息
*/
String gm_cmd_prefix = "gm convert -auto-orient -strip -flatten ";
String suffix = this.getImageTypeSuffix(imageDocInfo);
/**
* 开启了后显示为开启指定帧来提供性能
*/
if (this.gif2jpg && StringUtils.equalsIgnoreCase("gif", suffix)) { //若是 gif 且开了 gif 2 jpg 显示加上格式转换为 jpg
pic_src += "[0]"; // 选择 gif 指定帧
}
//String cmd = MessageFormat.format("gm convert -auto-orient -size {0, number,#}x{1, number,#} {2} -resize \"{0, number,#}x{1, number,#}^>\" +profile \"*\" {3}",
String cmd = MessageFormat.format(gm_cmd_prefix + " -size {0, number,#}x{1, number,#} {2} -resize \"{0, number,#}x>\" +profile \"*\" {3}",
width,
height,
pic_src,
pic_desc);
/**
* http://www.jb51.net/article/25856.htm
*
* -background white -gravity center -extent 100x100
* 扩展为 100*100 大小,不足使用白色背景填充
*
*/
if (width == 100 && height == 100) { //最小尺寸的缩略图,需要填充白色背景
cmd = MessageFormat.format(gm_cmd_prefix + " -size {0, number,#}x{1, number,#} {2} -resize {0, number,#}x{1, number,#} +profile \"*\" -quality 95 -background white -gravity center -extent 100x100 {3}",
width,
height,
pic_src,
pic_desc);
/**
* -background white
* 这个参数会导致 gif 的小图只有第一帧是正常的
*/
if (!this.gif2jpg) { // 开启了 gif 转 gif
if (StringUtils.equalsIgnoreCase("gif", suffix)) {
cmd = MessageFormat.format(gm_cmd_prefix + " -size {0, number,#}x{1, number,#} {2} -resize {0, number,#}x{1, number,#} +profile \"*\" -quality 95 -gravity center -extent 100x100 {3}",
width,
height,
pic_src,
pic_desc);
}
}
}
this.runCommand(cmd);
FileMetadata metadata = new MongoFileMetadata();
metadata.put("filename", desc.getName());
metadata.put("original_image_id", imageId);
// 保存到mongodb
MongoFAO mfao = (MongoFAO) FAOFactory.getInstance();
tempFileInputStream = new FileInputStream(desc);
String fileId = mfao.saveFile(tempFileInputStream, metadata);
return fileId;
} catch (Exception e) {
String message = " image id: " + imageId + ". " + e.getMessage();
logger.warn(message, e);
/**
* copy 出错文件到到一个文件夹
*/
File debug = new File("/kingdee/debug/uploadimage/");
if (debug.exists() && debug.isDirectory()) {
try {
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File debugdir = new File(debug.getAbsolutePath() + "/" + date);
if (!debugdir.exists() && debugdir.mkdirs()) {
this.runCommand(" cp " + soruce.getAbsolutePath() + " " + debugdir.getAbsolutePath() );
logger.info("copy " + soruce.getAbsolutePath() + " to " + debugdir.getAbsolutePath());
}
} catch (Exception e1) {
logger.warn(message, e);
}
}
throw new RuntimeException(message, e);
} finally {
IOUtils.closeQuietly(tempFileInputStream);
if (soruce.exists()) {
soruce.delete();
}
if (desc.exists()) {
desc.delete();
}
}
}
/**
* 新版本的图片缩率图
* @param imageId
* @return
* @throws IOException
*/
public String yzjResizeImage(final String imageId, final int pix) throws IOException {
DocumentInfo imageDocInfo = fileService.findById(imageId);
if(imageDocInfo == null) {
throw new IOException("Image["+imageId+"] not found!");
}
File desc = this.getDesc(imageDocInfo);
File soruce = this.getSource(imageDocInfo);
InputStream tempFileInputStream = null;
try {
String pic_src = soruce.getAbsolutePath();
String pic_desc = desc.getAbsolutePath();
/**
* -auto-orient 自动将图片旋转为正方向
* -strip 去除掉多余的信息
*/
String gm_cmd_prefix = "gm convert -auto-orient -strip -flatten ";
String suffix = this.getImageTypeSuffix(imageDocInfo);
/**
* 开启了后显示为开启指定帧来提供性能
*/
if (this.gif2jpg && StringUtils.equalsIgnoreCase("gif", suffix)) { //若是 gif 且开了 gif 2 jpg 显示加上格式转换为 jpg
pic_src += "[0]"; // 选择 gif 指定帧
}
// SimpleImageInfo imageInfo = new SimpleImageInfo(new FileInputStream(soruce));
//
// int srcWidth = imageInfo.getWidth();
// int srcHeight = imageInfo.getHeight();
//通过文件的类型获取
// String contextType = imageDocInfo.getContentType();
// String format = imageDocInfo.getFileExt();
// if (!StringUtils.isEmpty(contextType)) {
// String[] types = contextType.split("/");
// if (types != null && types.length == 2) {
// format = types[1];
// logger.info("format form content type" + contextType + " , format: " + format);
// }
// }
// Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(format);
// //通过文件的后缀获取
//
// ImageReader reader = readers.next();
// FileInputStream fileInputStream = new FileInputStream(soruce);
// ImageInputStream input = ImageIO.createImageInputStream(fileInputStream);
// reader.setInput(input, true);
// int srcWidth = reader.getWidth(0);
// int srcHeight = reader.getHeight(0);
// IOUtils.closeQuietly(fileInputStream);
SimpleImageInfo sii = new SimpleImageInfo(soruce);
int srcWidth = sii.getWidth();
int srcHeight = sii.getHeight();
String cmd = "";
cmd = yzjNewRule(pic_src, pic_desc, gm_cmd_prefix, srcWidth, srcHeight);
if (pix == 314) {
cmd = this.blNewRule(pic_src, pic_desc, gm_cmd_prefix, srcWidth, srcHeight);
}
this.runCommand(cmd);
FileMetadata metadata = new MongoFileMetadata();
metadata.put("filename", desc.getName());
metadata.put("original_image_id", imageId);
// 保存到mongodb
MongoFAO mfao = (MongoFAO) FAOFactory.getInstance();
tempFileInputStream = new FileInputStream(desc);
String fileId = mfao.saveFile(tempFileInputStream, metadata);
return fileId;
} catch (Exception e) {
String message = " image id: " + imageId + ". " + e.getMessage();
logger.warn(message, e);
/**
* copy 出错文件到到一个文件夹
*/
File debug = new File("/kingdee/debug/uploadimage/");
if (debug.exists() && debug.isDirectory()) {
try {
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File debugdir = new File(debug.getAbsolutePath() + "/" + date);
if (!debugdir.exists() && debugdir.mkdirs()) {
this.runCommand(" cp " + soruce.getAbsolutePath() + " " + debugdir.getAbsolutePath() );
logger.info("copy " + soruce.getAbsolutePath() + " to " + debugdir.getAbsolutePath());
}
} catch (Exception e1) {
logger.warn(message, e);
}
}
throw new RuntimeException(message, e);
} finally {
IOUtils.closeQuietly(tempFileInputStream);
if (soruce.exists()) {
soruce.delete();
}
if (desc.exists()) {
desc.delete();
}
}
}
private String yzjNewRule(String pic_src, String pic_desc,
String gm_cmd_prefix, int srcWidth, int srcHeight) {
String cmd = "" ;
if (srcHeight == srcWidth) { //相等时云之家规则为罗略图 280*280
cmd = MessageFormat.format(gm_cmd_prefix + " -size {0, number,#}x{1, number,#} {2} -resize \"{0, number,#}x{1, number,#}\" +profile \"*\" -quality 90 {3}",
280,
280,
pic_src,
pic_desc);
} else if (srcWidth < srcHeight) { // 保持云之家的 高度 280 个像素
double s = srcWidth/(srcHeight*1.0);
if (s <= 1/3.0) { //超高图,宽度 110 像素等比缩放
cmd = MessageFormat.format(gm_cmd_prefix + " {2} -thumbnail \"110x280^\" -extent 110x280 +profile \"*\" -quality 90 {3}",
280,
280,
pic_src,
pic_desc);
} else {
cmd = MessageFormat.format(gm_cmd_prefix + " {2} -resize \"x280\" +profile \"*\" -quality 90 {3}",
280,
280,
pic_src,
pic_desc);
}
} else if (srcWidth > srcHeight) { // 保持云之家的 宽度 280 个像素
double s = srcWidth/(srcHeight*1.0);
if (s >= 3) { //超宽图 限制高度 110 像素等比缩放
cmd = MessageFormat.format(gm_cmd_prefix + " {2} -thumbnail \"^280x110\" -gravity center -extent 280x110 +profile \"*\" -quality 90 {3}",
280,
280,
pic_src,
pic_desc);
} else {
cmd = MessageFormat.format(gm_cmd_prefix + " {2} -resize \"280x\" +profile \"*\" -quality 90 {3}",
280,
280,
pic_src,
pic_desc);
}
}
return cmd;
}
private String blNewRule(String pic_src, String pic_desc,
String gm_cmd_prefix, int srcWidth, int srcHeight) {
String cmd = "";
if (srcHeight == srcWidth) { //相等时云之家规则为罗略图 314*314
cmd = MessageFormat.format(gm_cmd_prefix + " -size {0, number,#}x{1, number,#} {2} -resize \"{0, number,#}x{1, number,#}\" +profile \"*\" -quality 90 {3}",
314,
314,
pic_src,
pic_desc);
} else if (srcWidth < srcHeight) { // 保持云之家的 高度 314 个像素
/**
* gm convert 3.png -thumbnail "314x314^" -gravity center -extent 314x314 3-314.png
*/
cmd = MessageFormat.format(gm_cmd_prefix + " {2} -thumbnail \"314x314^\" -gravity center -extent 314x314 +profile \"*\" -quality 90 {3}",
280,
280,
pic_src,
pic_desc);
} else if (srcWidth > srcHeight) { // 保持云之家的 宽度 280 个像素
cmd = MessageFormat.format(gm_cmd_prefix + " {2} -thumbnail \"^314x314\" -gravity center -extent 314x314 +profile \"*\" -quality 90 {3}",
280,
280,
pic_src,
pic_desc);
}
return cmd;
}
private static String getTempDir() {
if (tmpdir == null) {
tmpdir = AccessController.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty("java.io.tmpdir");
}
});
}
return tmpdir;
}
@Override
public Map<String, Dimension> resizeAvatar(String imageId) throws IOException {
Map<String, Dimension> ret = new LinkedHashMap<String, Dimension>(ImageService.USER_IMAGE_SPECS.length);
for (int i = 0; i < ImageService.USER_IMAGE_SPECS.length; i++) {
String newImageId = resizeImage(imageId,ImageService.USER_IMAGE_SPECS[i],ImageService.USER_IMAGE_SPECS[i]);
ret.put(newImageId, new Dimension(ImageService.USER_IMAGE_SPECS[i], ImageService.USER_IMAGE_SPECS[i]));
}
return ret;
}
/**
* 缩小,$thumb_size 宽高相同,
* $show_size宽固定,高自适应;
* $mobile_size:手机用,宽高都不超过1280
*/
@Override
public String[] thumbnailImage(final String imageId, int thumbnailSize, int showSize, int bigSize) throws IOException {
String[] ret = new String[5];
ret[0] = resizeImage(imageId, thumbnailSize, thumbnailSize);
ret[1] = resizeImage(imageId, showSize, showSize);
ret[2] = resizeImage(imageId, bigSize, bigSize);
ret[3] = this.yzjResizeImage(imageId, 280);
ret[4] = this.yzjResizeImage(imageId, 314);
return ret;
}
@Override
public String resizeImageToH(String imageId, int height, int maxWidth) throws IOException {
DocumentInfo imageDocInfo = fileService.findById(imageId);
File desc = this.getDesc(imageDocInfo);
File soruce = this.getSource(imageDocInfo);
InputStream tempFileInputStream = null;
try {
String pic_src = soruce.getAbsolutePath();
String pic_desc = desc.getAbsolutePath();
/**
* -auto-orient 自动将图片旋转为正方向
* -strip 去除掉多余的信息
*/
String gm_cmd_prefix = "gm convert -auto-orient -strip -flatten ";
String suffix = this.getImageTypeSuffix(imageDocInfo);
/**
* 开启了后显示为开启指定帧来提供性能
*/
if (this.gif2jpg && StringUtils.equalsIgnoreCase("gif", suffix)) { //若是 gif 且开了 gif 2 jpg 显示加上格式转换为 jpg
pic_src += "[0]"; // 选择 gif 指定帧
}
//String cmd = MessageFormat.format("gm convert -auto-orient -size {0, number,#}x{1, number,#} {2} -resize \"{0, number,#}x{1, number,#}^>\" +profile \"*\" {3}",
String cmd = MessageFormat.format(gm_cmd_prefix + " -resize \"{0, number,#}x{1, number,#}>\" +profile \"*\" -quality 95 {2} {3}",
maxWidth,
height,
pic_src,
pic_desc);
this.runCommand(cmd);
FileMetadata metadata = new MongoFileMetadata();
metadata.put("filename", desc.getName());
metadata.put("original_image_id", imageId);
// 保存到mongodb
MongoFAO mfao = (MongoFAO) FAOFactory.getInstance();
tempFileInputStream = new FileInputStream(desc);
String fileId = mfao.saveFile(tempFileInputStream, metadata);
return fileId;
} catch (Exception e) {
String message = " image id: " + imageId + ". " + e.getMessage();
logger.warn(message, e);
/**
* copy 出错文件到到一个文件夹
*/
File debug = new File("/kingdee/debug/uploadimage/");
if (debug.exists() && debug.isDirectory()) {
try {
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File debugdir = new File(debug.getAbsolutePath() + "/" + date);
if (!debugdir.exists() && debugdir.mkdirs()) {
this.runCommand(" cp " + soruce.getAbsolutePath() + " " + debugdir.getAbsolutePath() );
logger.info("copy " + soruce.getAbsolutePath() + " to " + debugdir.getAbsolutePath());
}
} catch (Exception e1) {
logger.warn(message, e);
}
}
throw new RuntimeException(message, e);
} finally {
IOUtils.closeQuietly(tempFileInputStream);
if (soruce.exists()) {
soruce.delete();
}
if (desc.exists()) {
desc.delete();
}
}
// return this.javaImageUtil.resizeImageToH(imageId, height, maxWidth);
}
@Override
public String genNetworkLogoAndText(String imageId, String text, int NETWORK_IMAGE_HEGIHT,
int NETWORK_IMAGE_MAX_WITH) throws IOException {
return this.javaImageUtil.genNetworkLogoAndText(imageId, text, NETWORK_IMAGE_HEGIHT, NETWORK_IMAGE_MAX_WITH);
}
@Override
public String imageText(String text) throws IOException {
return this.javaImageUtil.imageText(text);
}
@Override
public Dimension getImgSize(String id) throws IOException {
DocumentInfo imageDocInfo = fileService.findById(id);
BufferedImage srcImage = null;
try {
// srcImage = ImageIO.read(imageDocInfo.getInputStream());
// int srcWidth = srcImage.getWidth(null);
// int srcHeight = srcImage.getHeight(null);
//通过文件的类型获取
String contextType = imageDocInfo.getContentType();
String format = imageDocInfo.getFileExt();
if (!StringUtils.isEmpty(contextType)) {
String[] types = contextType.split("/");
if (types != null && types.length == 2) {
format = types[1];
logger.info("format form content type" + contextType + " , format: " + format);
}
}
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(format);
//通过文件的后缀获取
ImageReader reader = readers.next();
ImageInputStream input = ImageIO.createImageInputStream(imageDocInfo.getInputStream());
reader.setInput(input, true);
int srcWidth = reader.getWidth(0);
int srcHeight = reader.getHeight(0);
try{
input.close();
}catch(Throwable ex){}
return new Dimension(srcWidth, srcHeight);
} finally {
// 清理动作
if (imageDocInfo != null && imageDocInfo.getInputStream() != null) {
try {
imageDocInfo.getInputStream().close();
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
// 释放imageBuffer
if (srcImage != null) {
try {
srcImage.flush();
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
}
}
@Override
public Map<String, Dimension> resizeBatch(String imageId, String sizes) throws IOException {
String[] GROUP_IMAGE_SPECS = sizes.split(",");
Map<String, Dimension> ret = new LinkedHashMap<String, Dimension>(GROUP_IMAGE_SPECS.length);
for (int i = 0; i < GROUP_IMAGE_SPECS.length; i++) {
String newImageId = resizeImage(imageId,Integer.parseInt(GROUP_IMAGE_SPECS[i]),Integer.parseInt(GROUP_IMAGE_SPECS[i]));
ret.put(newImageId, new Dimension(Integer.parseInt(GROUP_IMAGE_SPECS[i]),Integer.parseInt(GROUP_IMAGE_SPECS[i])));
}
return ret;
}
@Override
public String genCompanyShortNameImage(String text, ImageType type) throws IOException {
return this.javaImageUtil.genCompanyShortNameImage(text, type);
}
/**
* 没有使用到
*/
@Override
public String compositeAvatar(String[] avatars, int avatar_size, int spacing, int padding, boolean is_mask)
throws IOException {
// TODO Auto-generated method stub
return this.javaImageUtil.compositeAvatar(avatars, avatar_size, spacing, padding, is_mask);
}
void runCommand(String cmd) throws Exception {
logger.info("Running command:" + cmd);
String[] cmds = { "sh", "-c", cmd };
if (WINDOW_OS) { // 兼容 win
cmds = new String[]{"cmd.exe", "/c", cmd };
}
Process p = Runtime.getRuntime().exec(cmds);
p.waitFor();
InputStream in = p.getInputStream();
InputStream error = p.getErrorStream();
String sError = org.apache.commons.io.IOUtils.toString(error);
if (!StringUtils.isEmpty(sError)) {
logger.error("runCommand[" + cmd + "]:" + sError);
throw new RuntimeException("runCommand error,please see error log!");
}
String s = org.apache.commons.io.IOUtils.toString(in);
logger.info("Running results:" + s);
}
// 获取图片类型
private String getImageTypeSuffix(DocumentInfo imageDocInfo) {
String fileName = imageDocInfo.getFileName();
String suffix = "";
if (fileName.lastIndexOf('.') != -1) {
suffix = fileName.substring(fileName.lastIndexOf('.') + 1);
}
if (suffix.length() == 0) {
suffix = imageDocInfo.getContentType().substring(imageDocInfo.getContentType().lastIndexOf('/') + 1);
}
return suffix;
}
/**
* 临时文件
*/
private File getDesc(DocumentInfo doc) {
String tempFileName = UUID.randomUUID().toString();
String suffix = this.getImageTypeSuffix(doc);
if (
// fix gif 转换消耗太多的时间
(StringUtils.equalsIgnoreCase("gif", suffix) && this.gif2jpg) ||
StringUtils.equalsIgnoreCase("png", suffix)) { // png 图片会透明处理
return new File(getTempDir(), tempFileName + ".jpg");
}
return new File(getTempDir(), tempFileName + "." + suffix);
}
/**
* 将 doc 转化为临时文件夹下的文件
*/
private File getSource(DocumentInfo doc) {
// 准备临时文件
String source = getTempDir() + "/source-" + doc.getFileID() + "." + getImageTypeSuffix(doc);
File tmpFile = new File(source);
InputStream is = null;
BufferedInputStream bif = null;
FileOutputStream fos = null;
try {
is = doc.getInputStream();
bif = new BufferedInputStream(is);
fos = new FileOutputStream(tmpFile);
byte[] bytes = new byte[1024];
for (int len = bif.read(bytes); len > -1; ) {
fos.write(bytes, 0, len);
len = bif.read(bytes);
}
return tmpFile;
} catch (Exception e) {
logger.warn(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
try {
if (fos != null) {
fos.flush();
}
} catch (IOException e) {
logger.warn(e.getMessage(), e);
}
IOUtils.closeQuietly(fos);
IOUtils.closeQuietly(bif);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment