net.coobird
thumbnailator
0.4.8
部分后缀图片会出现压缩失败
@Override
@Transactional(rollbackFor = Throwable.class)
public Picture uploadZip(MultipartFile file, String username) {
String originalFilename = "";//文件名称
// 文件保存路径
String filePatha = pictureUrl;//等同 C:/Users/admin/Desktop/url/picture #本地图片地址
String urlProduct = "";
Picture picture = new Picture();
try {
File addFile = new File(filePatha);
if (!addFile.exists()) {
addFile.mkdirs();
}
//如果出现同名文件,文件名后面加随机数
String findFfilePatha = filePatha + "/" + file.getOriginalFilename();
File addNameFile = new File(findFfilePatha);
if (!addNameFile.exists()) {
originalFilename = FileUtil.getFileNameNoEx(file.getOriginalFilename())+"."+ FileUtil.getExtensionName(file.getOriginalFilename());
}else{
originalFilename = FileUtil.getFileNameNoEx(file.getOriginalFilename()) + System.currentTimeMillis() +"."+ FileUtil.getExtensionName(file.getOriginalFilename());
}
filePatha += "/" + originalFilename;//绝对路径
urlProduct += "/" + originalFilename;//相对路径
// 转存文件
log.info("地址:" + filePatha);
log.info("文件大小:" + new BigDecimal((double)file.getSize()/1024/1024).divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP)+"M");
log.info("文件名" + originalFilename);
File file_a = FileUtil.toFile(file);
BigDecimal a = new BigDecimal((double)file.getSize()/1024/1024).divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP);
BigDecimal b = new BigDecimal (0.5);
File file_b = new File(filePatha);
if(a.compareTo(b) == 1){//a大于b,压缩图片
//压缩图片
Thumbnails.of(file_a.getAbsolutePath()).scale(1f).outputQuality(0.25f).toFile(file_b.getAbsolutePath());
}else{
Files.copy(file_a.toPath(),file_b.toPath());//不压缩直接拷贝
}
//如果出现同名文件,文件名后面加随机数
//FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), new File(filePatha));
//multipartFile.transferTo(new File(filePatha));
//删除临时文件
/*FileUtil.deleteFile(addFile);
FileUtil.deleteFile(addNameFile);
FileUtil.deleteFile(file_a);*/
} catch (IOException e) {
e.printStackTrace();
}
picture.setCreateTime(new Timestamp(System.currentTimeMillis()));
picture.setSize(new BigDecimal((double)file.getSize()/1024/1024).divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP)+"M");
picture.setUsername(username);
picture.setFilename(originalFilename);
picture.setUrl("/static/picture" + urlProduct);//存本地相对地址
picture.setDelete(filePatha);
pictureRepository.save(picture);
return picture;
}
把图片转换成流文件
commons-io
commons-io
2.5
package me.zhengjie.utils;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.imageio.stream.FileImageOutputStream;
import java.io.*;
import java.net.URL;
/**
* 图片处理类
*
* @author honghe
*/
public class ImageTool {
private static Logger logger = LoggerFactory.getLogger(
ImageTool.class);
private static final long DEFAULT_SIZE = 200 * 1024;
/*public static void main(String[] args) {
String picUrl = "C:/Users/admin/Desktop/url/picture/═╝╞м20.png";
compress(picUrl,50);
}*/
/**
* @param picUrl 图片地址
* @param desFileSize 压缩大小
*/
public static byte[] compress(String picUrl, long desFileSize,String fileNameCopy) {
try {
URL url = new URL(picUrl);
byte[] imageBytes = IOUtils.toByteArray(url);
if (imageBytes == null || imageBytes.length <= 0) {
logger.error("图片资源加载失败,请检查链接地址!url:" + picUrl);
throw new RuntimeException("图片资源加载失败,请检查链接地址!url:" + picUrl);
}
if (imageBytes.length <= desFileSize * 1024) {
return imageBytes;
}
byte[] imageBytesCopy = imageBytes;
double accuracy = getAccuracy(imageBytes.length / 1024);
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("【图片压缩】 | 图片原大小={}kb | 压缩后大小={}kb | url={}",
imageBytesCopy.length / 1024, imageBytes.length / 1024, picUrl);
File file = new File(fileNameCopy);
if(!file.exists()) {
file.createNewFile();
}
FileWriter fileWriter =new FileWriter(file);
fileWriter.write("");
fileWriter.flush();
fileWriter.close();
FileImageOutputStream imageOutput = new FileImageOutputStream(new File(fileNameCopy));
imageOutput.write(imageBytes, 0, imageBytes.length);
imageOutput.close();
return imageBytes;
} catch (Exception e) {
logger.error("图片资源加载失败,请检查链接地址!url:" + picUrl);
throw new RuntimeException("图片资源加载失败,请检查链接地址!url:" + picUrl);
}
}
/**
* 对图片byte[]进行base64
*/
public static String base64ByPic(byte[] imageBatys) {
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(imageBatys);
}
/**
* base64字符串转换成图片
* 对字节数组字符串进行Base64解码并生成图
*
* @param imgStr base64字符串
* @param imgFilePath 图片存放路径
* @dateTime 2018-02-23 14:42:17
*/
public static boolean Base64ToImage(String imgStr, String imgFilePath) throws IOException {
OutputStream out = null;
if (StringUtils.isEmpty(imgStr)) {
return false;
}
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] b = decoder.decodeBuffer(imgStr);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {// 调整异常数据
b[i] += 256;
}
}
out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
return true;
} catch (Exception e) {
return false;
} finally {
if (out != null) {
out.close();
}
}
}
/**
* 自动调节精度(经验数值)
*
* @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;
}
}
/**
* 上传图片
* @param file
* @return
* @throws Exception
*/
@Log("上传图片")
@PostMapping(value = "/picturesProduct")
public ResponseEntity picturesProduct(@RequestParam MultipartFile file, String productUrl){
Picture picture = pictureProductService.uploadZip(file,SecurityUtils.getUsername());
Map map = new HashMap();
map.put("errno",0);
map.put("id",picture.getId());
map.put("data",new String[]{picture.getUrl()});
return new ResponseEntity(map,HttpStatus.OK);
}
/**
* 上传图片
* @param file
* @param username
* @return
*/
@CacheEvict(allEntries = true)
Picture uploadZip(MultipartFile file, String username);
@Override
@Transactional(rollbackFor = Throwable.class)
public Picture uploadZip(MultipartFile file, String username) {
String originalFilename = "";//文件名称
String originalFilenameBackup = "";//文件名称备份
// 文件保存路径
String filePatha = pictureUrl;
String filePathaBackup = pictureUrl;
String urlProduct = "";
Picture picture = new Picture();
try {
File addFile = new File(filePatha);
if (!addFile.exists()) {
addFile.mkdirs();
}
//如果出现同名文件,文件名后面加随机数
String findFfilePatha = filePatha + "/" + file.getOriginalFilename();
File addNameFile = new File(findFfilePatha);
if (!addNameFile.exists()) {
originalFilename = FileUtil.getFileNameNoEx(file.getOriginalFilename())+"."+ FileUtil.getExtensionName(file.getOriginalFilename());
originalFilenameBackup = FileUtil.getFileNameNoEx(file.getOriginalFilename())+"Backup."+ FileUtil.getExtensionName(file.getOriginalFilename());
}else{
originalFilename = FileUtil.getFileNameNoEx(file.getOriginalFilename()) + System.currentTimeMillis() +"."+ FileUtil.getExtensionName(file.getOriginalFilename());
originalFilenameBackup = FileUtil.getFileNameNoEx(file.getOriginalFilename()) + System.currentTimeMillis() +".Backup"+ FileUtil.getExtensionName(file.getOriginalFilename());
}
filePatha += "/" + originalFilename;//绝对路径
filePathaBackup += "/" + originalFilenameBackup;//备份文件
urlProduct += "/" + originalFilename;//相对路径
// 转存文件
log.info("地址:" + filePatha);
log.info("文件大小:" + new BigDecimal((double)file.getSize()/1024/1024).divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP)+"M");
log.info("文件名" + originalFilename);
File file_a = FileUtil.toFile(file);
BigDecimal a = new BigDecimal((double)file.getSize()/1024/1024).divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP);
BigDecimal b = new BigDecimal (0.3);//超过0.3M的图片进行压缩
File file_b = new File(filePatha);
if(a.compareTo(b) == 1){//a大于b,压缩图片
//压缩图片
//第一种方法 部分格式图片会压缩失败
//Thumbnails.of(file_a.getAbsolutePath()).scale(1f).outputQuality(0.25f).toFile(file_b.getAbsolutePath());
//第二种 流文件
File file_c = new File(filePathaBackup);//备份数据
Files.copy(file_a.toPath(),file_c.toPath());//不压缩直接拷贝
ImageTool.compress("file:" + filePathaBackup,2000,file_b.getAbsolutePath());
log.info("压缩成功:" + file_b.getAbsolutePath());
}else{
Files.copy(file_a.toPath(),file_b.toPath());//不压缩直接拷贝
}
} catch (IOException e) {
e.printStackTrace();
}
picture.setCreateTime(new Timestamp(System.currentTimeMillis()));
picture.setSize(new BigDecimal((double)file.getSize()/1024/1024).divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP)+"M");
picture.setUsername(username);
picture.setFilename(originalFilename);
picture.setUrl("/static/picture" + urlProduct);//存本地相对地址
picture.setDelete(filePatha);
pictureRepository.save(picture);
return picture;
}
//按指定大小把图片进行缩和放(会遵循原图高宽比例)
/此处把图片压成400×500的缩略图
Thumbnails.of(fromPic).size(400,500).toFile(toPic);//变为400*300,遵循原图比例缩或放到400*某个高度
//按照比例进行缩小和放大
Thumbnails.of(fromPic).scale(0.2f).toFile(toPic);//按比例缩小
Thumbnails.of(fromPic).scale(2f);//按比例放大
//不按比例,就按指定的大小进行缩放
Thumbnails.of(fromPic).size(100, 100).keepAspectRatio(false).toFile(toPic);
//或者Thumbnails.of(fromPic).forceSize(100,100).toFile(toPic);
//旋转图片,rotate(角度),正数则为顺时针,负数则为逆时针
Thumbnails.of(fromPic).size(200,200).rotate(90).toFile(toPic);
//图片尺寸不变,压缩图片文件大小outputQuality实现,参数1为最高质量
Thumbnails.of(fromPic).scale(1f).outputQuality(0.25f).toFile(toPic);
//给图片加水印,watermark(位置,水印图,透明度)Positions.CENTER表示加在中间
Thumbnails.of(fromPic).size(400,400)
.watermark(Positions.CENTER,ImageIO.read(waterPic),0.5f)
.outputQuality(0.8f).toFile(toPic);
//用sourceRegion()实现图片裁剪
//图片中心300*300的区域,Positions.CENTER表示中心,还有许多其他位置可选
Thumbnails.of(fromPic).sourceRegion(Positions.CENTER,300,300)
.size(300,300).toFile(toPic);
//图片中上区域300*300的区域
Thumbnails.of(fromPic).sourceRegion(Positions.TOP_CENTER,300,300)
.size(300,300).toFile(toPic);
格式由jpg变为png,图片大小没变。
//用outputFormat(图像格式)转换图片格式,保持原尺寸不变
Thumbnails.of(fromPic).scale(1f).outputFormat("png")
.toFile("picture/png格式的图片.png");
//输出成文件流OutputStream
OutputStream os=new FileOutputStream(toPic);
Thumbnails.of(fromPic).size(120,120).toOutputStream(os);
//输出BufferedImage,asBufferedImage()返回BufferedImage
BufferedImage bi=Thumbnails.of(fromPic).size(120,120).asBufferedImage();
ImageIO.write(bi,"jpg",toPic);
//压缩至指定图片尺寸(例如:横400高300),保持图片不变形,多余部分裁剪掉(这个是引的网友的代码)
BufferedImage image = ImageIO.read(fromPic);
Builder builder = null;
int imageWidth = image.getWidth();
int imageHeitht = image.getHeight();
if ((float)300 / 400 != (float)imageWidth / imageHeitht) {
if (imageWidth > imageHeitht) {
image = Thumbnails.of(fromPic).height(300).asBufferedImage();
} else {
image = Thumbnails.of(fromPic).width(400).asBufferedImage();
}
builder = Thumbnails.of(image).sourceRegion(Positions.CENTER, 400, 300).size(400, 300);
} else {
builder = Thumbnails.of(image).size(400, 300);
}
builder.outputFormat("jpg").toFile(toPic);
参考作者:https://blog.csdn.net/chenleixing/article/details/44685817