文件工具类
导入坐标:
<!--工具包--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>${hutool.version}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
工具类中的方法
1. toFile:MultipartFile转File
参数:MultipartFile multipartFile
2. getExtensionName:获取文件扩展名,不带 .
参数:String filename
3. getFileNameNoEx:Java文件操作 获取不带扩展名的文件名
参数:String filename
4. getSize:文件大小转换
参数:long size
5. inputStreamToFile:inputStream 转 File
参数:InputStream ins, String name
6. upload:将文件名解析成文件的上传路径
MultipartFile file, String filePath
7. downloadExcel:导出excel
参数:List<Map<String, Object>> list, HttpServletResponse response
8. getFileType:获取文件类型
参数:String type
9. getTransferFileType:获取文件类型英文名
参数:String type
10. checkSize:检测文件是否超出允许范围
参数:long maxSize, long size
11. check:判断两个文件是否相同
参数:File file1, File file2
12. getByte:获取文件字节长度
参数:File file
13. getMd5:将字节数组转换为16进制字符
参数:byte[] bytes
14. downloadFile:下载文件
参数:HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit
代码如下:
/* * Copyright 2019-2020 Zheng Jie * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.team.utils; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.poi.excel.BigExcelWriter; import cn.hutool.poi.excel.ExcelUtil; import com.team.exception.BadRequestException; import org.apache.poi.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.security.MessageDigest; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; /** * File工具类,扩展 hutool 工具包 * */ public class FileUtil extends cn.hutool.core.io.FileUtil { private static final Logger log = LoggerFactory.getLogger(FileUtil.class); /** * 系统临时目录 * <br> * windows 包含路径分割符,但Linux 不包含, * 在windows \\==\ 前提下, * 为安全起见 同意拼装 路径分割符, * <pre> * java.io.tmpdir * windows : C:\Users/xxx\AppData\Local\Temp\ * linux: /temp * </pre> */ public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator; /** * 定义GB的计算常量 */ private static final int GB = 1024 * 1024 * 1024; /** * 定义MB的计算常量 */ private static final int MB = 1024 * 1024; /** * 定义KB的计算常量 */ private static final int KB = 1024; /** * 格式化小数 */ private static final DecimalFormat DF = new DecimalFormat("0.00"); /** * MultipartFile转File */ public static File toFile(MultipartFile multipartFile) { // 获取文件名 String fileName = multipartFile.getOriginalFilename(); // 获取文件后缀 String prefix = "." + getExtensionName(fileName); File file = null; try { // 用uuid作为文件名,防止生成的临时文件重复 file = File.createTempFile(IdUtil.simpleUUID(), prefix); // MultipartFile to File multipartFile.transferTo(file); } catch (IOException e) { log.error(e.getMessage(), e); } return file; } /** * 获取文件扩展名,不带 . */ public static String getExtensionName(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length() - 1))) { return filename.substring(dot + 1); } } return filename; } /** * Java文件操作 获取不带扩展名的文件名 */ public static String getFileNameNoEx(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length()))) { return filename.substring(0, dot); } } return filename; } /** * 文件大小转换 */ public static String getSize(long size) { String resultSize; if (size / GB >= 1) { //如果当前Byte的值大于等于1GB resultSize = DF.format(size / (float) GB) + "GB "; } else if (size / MB >= 1) { //如果当前Byte的值大于等于1MB resultSize = DF.format(size / (float) MB) + "MB "; } else if (size / KB >= 1) { //如果当前Byte的值大于等于1KB resultSize = DF.format(size / (float) KB) + "KB "; } else { resultSize = size + "B "; } return resultSize; } /** * inputStream 转 File */ static File inputStreamToFile(InputStream ins, String name) throws Exception { File file = new File(SYS_TEM_DIR + name); if (file.exists()) { return file; } OutputStream os = new FileOutputStream(file); int bytesRead; int len = 8192; byte[] buffer = new byte[len]; while ((bytesRead = ins.read(buffer, 0, len)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); ins.close(); return file; } /** * 将文件名解析成文件的上传路径 */ public static File upload(MultipartFile file, String filePath) { Date date = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); String name = getFileNameNoEx(file.getOriginalFilename()); String suffix = getExtensionName(file.getOriginalFilename()); String nowStr = "-" + format.format(date); try { String fileName = name + nowStr + "." + suffix; String path = filePath + fileName; // getCanonicalFile 可解析正确各种路径 File dest = new File(path).getCanonicalFile(); // 检测是否存在目录 if (!dest.getParentFile().exists()) { if (!dest.getParentFile().mkdirs()) { System.out.println("was not successful."); } } // 文件写入 file.transferTo(dest); return dest; } catch (Exception e) { log.error(e.getMessage(), e); } return null; } /** * 导出excel */ public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException { String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; File file = new File(tempPath); BigExcelWriter writer = ExcelUtil.getBigWriter(file); // 一次性写出内容,使用默认样式,强制输出标题 writer.write(list, true); //response为HttpServletResponse对象 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); ServletOutputStream out = response.getOutputStream(); // 终止后删除临时文件 file.deleteOnExit(); writer.flush(out, true); //此处记得关闭输出Servlet流 IoUtil.close(out); } public static String getFileType(String type) { String documents = "txt pdf pps wps doc docx ppt pptx xls xlsx"; String music = "mp3 wav wma mpa ram ra aac aif m4a"; String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; if (image.contains(type)) { return "图片"; } else if (documents.contains(type)) { return "文档"; } else if (music.contains(type)) { return "音乐"; } else if (video.contains(type)) { return "视频"; } else { return "其他"; } } public static String getTransferFileType(String type) { String documents = "txt pdf pps wps doc docx ppt pptx xls xlsx"; String music = "mp3 wav wma mpa ram ra aac aif m4a"; String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; if (image.contains(type)) { return "image"; } else if (documents.contains(type)) { return "documents"; } else if (music.contains(type)) { return "music"; } else if (video.contains(type)) { return "video"; } else { return "other"; } } public static void checkSize(long maxSize, long size) { // 1M int len = 1024 * 1024; if (size > (maxSize * len)) { throw new BadRequestException("文件超出规定大小"); } } /** * 判断两个文件是否相同 */ public static boolean check(File file1, File file2) { String img1Md5 = getMd5(file1); String img2Md5 = getMd5(file2); return img1Md5.equals(img2Md5); } /** * 判断两个文件是否相同 */ public static boolean check(String file1Md5, String file2Md5) { return file1Md5.equals(file2Md5); } private static byte[] getByte(File file) { // 得到文件长度 byte[] b = new byte[(int) file.length()]; try { InputStream in = new FileInputStream(file); try { System.out.println(in.read(b)); } catch (IOException e) { log.error(e.getMessage(), e); } } catch (FileNotFoundException e) { log.error(e.getMessage(), e); return null; } return b; } private static String getMd5(byte[] bytes) { // 16进制字符 char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; try { MessageDigest mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(bytes); byte[] md = mdTemp.digest(); int j = md.length; char[] str = new char[j * 2]; int k = 0; // 移位 输出字符串 for (byte byte0 : md) { str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { log.error(e.getMessage(), e); } return null; } /** * 下载文件 * * @param request / * @param response / * @param file / */ public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { response.setCharacterEncoding(request.getCharacterEncoding()); response.setContentType("application/octet-stream"); FileInputStream fis = null; try { fis = new FileInputStream(file); response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); IOUtils.copy(fis, response.getOutputStream()); response.flushBuffer(); } catch (Exception e) { log.error(e.getMessage(), e); } finally { if (fis != null) { try { fis.close(); if (deleteOnExit) { file.deleteOnExit(); } } catch (IOException e) { log.error(e.getMessage(), e); } } } } public static String getMd5(File file) { return getMd5(getByte(file)); } }
获取图片响应流操作
流操作
传入参数:
1. src:本地图片路径
2. response:HttpServletResponse对象
/** * @param src * @param response * */ //获取图片 public static void getImageSteam(String src, HttpServletResponse response) { File file = new File(src); //System.out.println("文件名---" + file.getName()); //获取文件后缀名 String extensionName = FileUtil.getExtensionName(file.getName()); //System.out.println("后缀名---" + extensionName); //设置响应数据类型(后缀名) response.setContentType("image/" + extensionName); FileInputStream in = null; ServletOutputStream out = null; try { in = new FileInputStream(file); out = response.getOutputStream(); byte[] bytes = new byte[1024 * 10]; int len = 0; while ((len = in.read(bytes)) != -1) { out.write(bytes, 0, len); } out.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * @param fileName * @param response 获取图片的方法 */ @GetMapping("/getImage") @AnonymousAccess @Transactional public void getImage(@RequestParam String fileName, HttpServletResponse response) { System.out.println("文件名---" + fileName); FeedbackImages image = feedbackService.findImageByName(fileName); String src = image.getSrc(); System.out.println("文件路径---" + src); /*使用ImageUtil的封装方法*/ ImageUtil.getImageSteam(src, response); }
获取视频响应流操作
传入参数:
1. src:本地图片路径
2. response:HttpServletResponse对象
/** * @param src * @param response * */ //获取视频文件 public static void getImageSteam(String src, HttpServletResponse response) { File file = new File(src); //System.out.println("文件名---" + file.getName()); //获取文件后缀名 String extensionName = FileUtil.getExtensionName(file.getName()); //System.out.println("后缀名---" + extensionName); //设置响应数据类型(后缀名) response.setContentType("video/" + extensionName); FileInputStream in = null; ServletOutputStream out = null; try { in = new FileInputStream(file); out = response.getOutputStream(); byte[] bytes = new byte[1024 * 10]; int len = 0; while ((len = in.read(bytes)) != -1) { out.write(bytes, 0, len); } out.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * @param fileName * @param response 获取视频的方法 */ @GetMapping("/getVideo") @AnonymousAccess @Transactional public void getVideo(@RequestParam String fileName, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { response.setHeader("Content-Type", "video/mp4"); System.out.println("文件名---" + fileName); FeedbackImages image = feedbackService.findImageByName(fileName); String src = image.getSrc(); System.out.println("文件路径---" + src); /*使用ImageUtil的封装方法*/ ImageUtil.getVideoSteam(src, response); }
获取视频响应流(断点传输)
特别注意:如果使用上述的方法直接对视频进行流传输,会出现一个问题:在前端使用video标签读取视频时,视频无法拖动进度条,只能一直从头播放到尾,缺少了断点续传。(移动端好像不会)
因此在响应视频的文件流时,需要对文件进行字节切割,实现单点续传。
传入参数:
src:本地图片路径
response:HttpServletResponse对象
//获取视频 public static void getVideoSteam(String src, HttpServletRequest request, HttpServletResponse response) { BufferedInputStream bis = null; try { File file = new File(src); if (file.exists()) { long p = 0L; long toLength = 0L; long contentLength = 0L; int rangeSwitch = 0; // 0,从头开始的全文下载;1,从某字节开始的下载(bytes=27000-);2,从某字节开始到某字节结束的下载(bytes=27000-39000) long fileLength; String rangBytes = ""; fileLength = file.length(); // get file content InputStream ins = new FileInputStream(file); bis = new BufferedInputStream(ins); // tell the client to allow accept-ranges response.reset(); response.setHeader("Accept-Ranges", "bytes"); // client requests a file block download start byte String range = request.getHeader("Range"); if (range != null && range.trim().length() > 0 && !"null".equals(range)) { response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT); rangBytes = range.replaceAll("bytes=", ""); if (rangBytes.endsWith("-")) { // bytes=270000- rangeSwitch = 1; p = Long.parseLong(rangBytes.substring(0, rangBytes.indexOf("-"))); contentLength = fileLength - p; // 客户端请求的是270000之后的字节(包括bytes下标索引为270000的字节) } else { // bytes=270000-320000 rangeSwitch = 2; String temp1 = rangBytes.substring(0, rangBytes.indexOf("-")); String temp2 = rangBytes.substring(rangBytes.indexOf("-") + 1, rangBytes.length()); p = Long.parseLong(temp1); toLength = Long.parseLong(temp2); contentLength = toLength - p + 1; // 客户端请求的是 270000-320000 之间的字节 } } else { contentLength = fileLength; } // 如果设设置了Content-Length,则客户端会自动进行多线程下载。如果不希望支持多线程,则不要设置这个参数。 // Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节] response.setHeader("Content-Length", new Long(contentLength).toString()); // 断点开始 // 响应的格式是: // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小] if (rangeSwitch == 1) { String contentRange = new StringBuffer("bytes ").append(new Long(p).toString()).append("-") .append(new Long(fileLength - 1).toString()).append("/") .append(new Long(fileLength).toString()).toString(); response.setHeader("Content-Range", contentRange); bis.skip(p); } else if (rangeSwitch == 2) { String contentRange = range.replace("=", " ") + "/" + new Long(fileLength).toString(); response.setHeader("Content-Range", contentRange); bis.skip(p); } else { String contentRange = new StringBuffer("bytes ").append("0-").append(fileLength - 1).append("/") .append(fileLength).toString(); response.setHeader("Content-Range", contentRange); } String fileName = file.getName(); response.setContentType("application/octet-stream"); response.addHeader("Content-Disposition", "attachment;filename=" + fileName); OutputStream out = response.getOutputStream(); int n = 0; long readLength = 0; int bsize = 1024; byte[] bytes = new byte[bsize]; if (rangeSwitch == 2) { // 针对 bytes=27000-39000 的请求,从27000开始写数据 while (readLength <= contentLength - bsize) { n = bis.read(bytes); readLength += n; out.write(bytes, 0, n); } if (readLength <= contentLength) { n = bis.read(bytes, 0, (int) (contentLength - readLength)); out.write(bytes, 0, n); } } else { while ((n = bis.read(bytes)) != -1) { out.write(bytes, 0, n); } } out.flush(); out.close(); bis.close(); } } catch (IOException ie) { // 忽略 ClientAbortException 之类的异常 } catch (Exception e) { e.printStackTrace(); } }
截取视频某帧图片
1、使用工具:ffmpeg,
官网下载地址:http://ffmpeg.org/download.html
自己提供的下载地址:
链接:https://pan.baidu.com/s/1x03SItqFfhl0LHGypxDqRA
提取码:obun
测试:
进入含有ffmpeg.exe的bin目录(也可以配置环境变量)
ffmpeg -i xxx.mp4 -y -f image2 -t 0.001 -s 125x125 xxx.jpg
运行成功后,将截取xxx.mp4的第0.0001秒的图片生成125*125的xxx.jpg图片
(注意视频、图片名称要带路径,否则当前目录)
其他f fmpeg 工具命令可以参考:https://blog.csdn.net/YZ099/article/details/108082980
使用java编写代码实现
获取成功返回true,获取失败返回false
传入参数:
1. ffmpegPath:ffmpeg.exe存放的路径
2. path:视频文件的存放路径
3. outImagePath:输出缩略图的保存路径
/** * 获得视频缩略图,获取成功返回true,获取失败返回false * * @param ffmpegPath 是ffmpeg.exe存放的路径 * @param path 是视频文件的存放路径 * @param outImagePath 输出缩略图的保存路径 * @return */ public static boolean SaveVideoThumbnail(String ffmpegPath, String path, String outImagePath) throws Exception { boolean flag = true; try { File file = new File(path); if (!file.exists()) { //判断视频文件是否存在 return false; } //设置参数 List<String> commands = new java.util.ArrayList<String>(); commands.add(ffmpegPath);//这里设置ffmpeg.exe存放的路径 commands.add("-i"); commands.add(path);//这里是设置要截取缩略图的视频的路径 commands.add("-y"); commands.add("-f"); commands.add("image2"); commands.add("-ss"); commands.add("1");//这里设置的是要截取视频开始播放多少秒后的图,可以自己设置时间 commands.add("-t"); commands.add("0.001"); //commands.add("-s"); //commands.add("660x660");//这里设置输出图片的大小 commands.add(outImagePath);//这里设置输出的截图的保存路径 //截取缩略图并保存 ProcessBuilder builder = new ProcessBuilder(); builder.command(commands); builder.start(); } catch (Exception e) { e.printStackTrace(); flag = false; System.out.println("获取视频缩略图失败"); } return flag; }
在获取的视频缩略图中间添加暂停按钮
思路:使用java GPU绘图工具Graphics2D,先将截取的视频图片绘画出来,然后再获取该图片的正中间位置,接着绘画出准备好的暂停按钮的图标图片,最后使用文件流导出图片。
传入参数:
1. bigPath:大图片的路径
2. smallPath:小图片的路径
/** * 在获取的视频缩略图中间添加暂停按钮 * * @param bigPath * @param smallPath * @throws IOException */ public static void mergeImage(String bigPath, String smallPath) throws IOException { try { BufferedImage small; BufferedImage big = ImageIO.read(new File(bigPath)); if (smallPath.contains("http")) { URL url = new URL(smallPath); small = ImageIO.read(url); } else { small = ImageIO.read(new File(smallPath)); } Graphics2D g = big.createGraphics(); int width = big.getWidth() - small.getWidth(); int height = big.getHeight() - small.getHeight(); float fx = width / 2; float fy = height / 2; int x_i = (int) fx; int y_i = (int) fy; // g.drawImage(small, x_i, y_i, small.getWidth(), small.getHeight(), null); g.drawImage(small, x_i, y_i, null); g.dispose(); ImageIO.write(big, "png", new File(bigPath)); } catch (Exception e) { e.printStackTrace(); } }
执行结果输出的图片
压缩图片
压缩一般分为三种情况:
1. 按图片的比例进行压缩
2. 直接设置图片压缩后的输出大小进行压缩
3. 按设置宽高对图片进行压缩
1. 按图片的比例进行压缩
思路:获取传进来的图片,获取该图片的宽高,计算出比例,然后根据传进来的要压缩结果宽度/比例得到要压缩结果的高度,接着按照要压缩结果的宽高进行对图片进行压缩,最后文件流输出图片。
传入参数:
1. srcImgPath:原图片路径
2. distImgPath: 转换大小后图片路径
3. width0:压缩结果的目标宽度
/*** * 功能 :调整图片大小 * @param srcImgPath 原图片路径 * @param distImgPath 转换大小后图片路径 * @param width0 按比例压缩图片,压缩后宽度为width0 */ public static void resizeImage(String srcImgPath, String distImgPath, int width0) throws IOException { File srcFile = new File(srcImgPath); Image srcImg = ImageIO.read(srcFile); BufferedImage buffImg = null; float width = ((BufferedImage) srcImg).getWidth(); float height = ((BufferedImage) srcImg).getHeight(); float scale = width / height; int height0 = (int) (width0 / scale); System.out.println(scale + ":" + width0 + "---" + height0); buffImg = new BufferedImage(width0, height0, BufferedImage.TYPE_INT_RGB); buffImg.getGraphics().drawImage( srcImg.getScaledInstance(width0, height0, Image.SCALE_SMOOTH), 0, 0, null); ImageIO.write(buffImg, "JPG", new File(distImgPath)); } public static void main(String[] args) { try { resizeImage("D:\\projects\\TS_Admin\\trunk\\team-system\\src\\main\\resources\\static\\images\\pause.png", "D:\\projects\\TS_Admin\\trunk\\team-system\\src\\main\\resources\\static\\images\\pause_100_100.png", 100); } catch (IOException e) { System.out.println("图片转换出现异常!"); } }
2. 直接设置图片压缩后的输出大小进行压缩
传入参数:
1. imageBytes:源图片字节数组
2. desFileSize: 指定图片大小,单位kb
3. imageId:影像编号
return: 压缩质量后的图片字节数组
代码如下:
/** * Created by tao. * Date: 2021/3/12 17:45 * 描述: */ public class PicUtils { private static Logger logger = LoggerFactory.getLogger(PicUtils.class); public static void main(String[] args) throws IOException { byte[] bytes = FileUtils.readFileToByteArray(new File("C:\\teamadmin\\file\\图片\\3a6372e3cfefec8144de4fc0585105dd.jpg")); long l = System.currentTimeMillis(); bytes = PicUtils.compressPicForScale(bytes, 50, "x");// 图片小于300kb System.out.println(System.currentTimeMillis() - l); FileUtils.writeByteArrayToFile(new File("C:\\teamadmin\\file\\图片\\3a6372e3cfefec8144de4fc0585105dd.jpg"), bytes); } /** * 根据指定大小压缩图片 * * @param imageBytes 源图片字节数组 * @param desFileSize 指定图片大小,单位kb * @param imageId 影像编号 * @return 压缩质量后的图片字节数组 */ public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize, String imageId) { if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) { return imageBytes; } long srcSize = imageBytes.length; double accuracy = getAccuracy(srcSize / 1024); try { while (imageBytes.length > desFileSize * 1024) { ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length); Thumbnails.of(inputStream) .scale(accuracy) .outputQuality(accuracy) .toOutputStream(outputStream); imageBytes = outputStream.toByteArray(); } logger.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb", imageId, srcSize / 1024, imageBytes.length / 1024); } catch (Exception e) { logger.error("【图片压缩】msg=图片压缩失败!", e); } return imageBytes; } /** * 自动调节精度(经验数值) * * @param size 源图片大小 * @return 图片压缩质量比 */ private static double getAccuracy(long size) { double accuracy; if (size < 900) { accuracy = 0.85; } else if (size < 2047) { accuracy = 0.6; } else if (size < 3275) { accuracy = 0.44; } else { accuracy = 0.4; } return accuracy; } }
3. 按设置宽高对图片进行压缩
传入参数:
1. srcImgPath:原图片路径
2. distImgPath: 转换大小后图片路径
3. width:压缩结果的目标宽度
4. height:压缩结果的目标高度
/*** * 功能 :调整图片大小 * @param srcImgPath 原图片路径 * @param distImgPath 转换大小后图片路径 */ public static void resizeImage(String srcImgPath, String distImgPath, int width,int height) throws IOException { File srcFile = new File(srcImgPath); Image srcImg = ImageIO.read(srcFile); BufferedImage buffImg = null; buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); buffImg.getGraphics().drawImage( srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); ImageIO.write(buffImg, "JPG", new File(distImgPath)); }
压缩结果