文件工具类
导入坐标:
代码语言:javascript复制<!--工具包-->
<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
代码如下:
代码语言:javascript复制/*
* 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/xxxAppDataLocalTemp
* 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对象
代码语言:javascript复制/**
* @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对象
代码语言:javascript复制/**
* @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对象
代码语言:javascript复制 //获取视频
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:输出缩略图的保存路径
代码语言:javascript复制 /**
* 获得视频缩略图,获取成功返回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:小图片的路径
代码语言:javascript复制/**
* 在获取的视频缩略图中间添加暂停按钮
*
* @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:压缩结果的目标宽度
代码语言:javascript复制 /***
* 功能 :调整图片大小
* @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: 压缩质量后的图片字节数组
代码如下:
代码语言:javascript复制/**
* 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:压缩结果的目标高度
代码语言:javascript复制/***
* 功能 :调整图片大小
* @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));
}
压缩结果