首页 > 其他分享 >Springboot图片上传压缩

Springboot图片上传压缩

时间:2024-08-05 18:20:46浏览次数:12  
标签:Springboot 压缩 String file import 上传 图片

原文链接:https://blog.csdn.net/hanerer1314/article/details/96175436

需求背景说明 最近后端管理项目中需要用到用户一些证件图片进行表单文件的上传 如果每个人的证件照片都非常大,对服务器资源将是一种浪费, 因为用户量也不是很大,所以也没对接第三方的OSS或者七牛云存储对象,就写个简单的图像压缩吧,我主要是提供了两种方式进行图片压缩,第一种是使用Java自带的Image绘制图像,输入指定的宽高尺寸,最后在重新绘制新的图片,核心代码也就三四行左右,压缩绘制算法都是JDK底层已经封装完成了,直接调用就行。
第二种是使用Google的压缩工具类Thumbnails 大名鼎鼎的不一般,只需要一行代码即可,可实现的功能那是相当的丰富,图像指定宽高压缩,原图压缩,添加水印,图像旋转,指定图像压缩质量比例等等。前端调用使用ajax通过表单对象形式获取文件,并设置formData参数传给后端。

先看一下ajax前端发送请求需要注意的事项,我没有直接使用html表单的形式,设置相应的表单属性来请求action操作,而是new 一个新的表单对象,然后获取标签属性上的元素 来封装成一个完整的对象如下:

需要注意的是上传文件时候data类型必须是formdata类型,Content-Type类型为: multipart/form-data; boundary=OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp,boundary是请求参数之间的界限标识,服务器会通过他来做参数隔离与获取,这个Content-Type并不是我们自己设置的,而是jQuery默认设置的formdata的Content-Type,如果我们自己设置了Content-Type,jQuery会通过设置的把原来默认的覆盖掉(默认jQuery会把ContentType设置为application/x-www-form-urlencoded),这样服务器在获取传入的参数时候会报错 no multipart boundary was found,当时也是想不明白是咋回事,因为服务器无法获取到boundary就无法区分参数与文件,所以我们的解决办法是把contentType设置为false,并把processData也设置为false,让那个jQuery不去处理formdata,如果不做限制jQuery会把formData转换成String类型,真的是有无穷多的细节在里面。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图片上传测试</title>
</head>
<body>
<div class="auth_wrapper">
<div class="picture picture1">
<span><h1>文件上传测试</h1></span>
<span></span>
</div>
<div class="auth_right">
<label>
<input id="file" type="file" name="file" accept="image/png, image/jpeg, image/jpg" style="left: -9999px; position: absolute;">
<div class="btn btn-default" onclick="change()">点我上传文件!!!</div>
</label>
<text class="load_img1_tip hidden"></text>
</div>
</div>
// 此处需要引入相关的jQuery.js文件可自己下载到本地也可CDN网址加载
<script type="text/javascript" src="../image/common/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="../image/common/jquery.actual.min.js"></script>
<script type="text/javascript" src="../image/common/bootstrap.min.js"></script>
<script type="text/javascript" src="../image/common/fileinput.min.js"></script>
<script type="text/javascript" src="../image/common/zh.js"></script>
<script>
/**
* 监听元素变化时候执行该方法 可以看出监听的元素是 <input>标签中的file元素 也可直接不用change方法 调用submit()方法 但是需要注意的是直接点击后调用该方法 当我们选择了
* 图片后不再再次出发上传图片的接口
*/
function change () {
$("#file").change(function () {
submit()
});
}
//上传图片到服务器 ajax 请求调用图片上传和压缩
function submit() {
var formdata = new FormData();
formdata.append('imageFile', $('#file')[0].files[0]);
$.ajax({
async: false,
type: 'POST',
url: "http://127.0.0.1:8001/file/upload",
dataType: 'json',
data: formdata,
contentType: false, //ajax上传图片需要添加
processData: false, //ajax上传图片需要添加
success: function (data) {
alert(data.responseText)
},
error: function (data) {
alert(data.responseText)
}
})
}
</script>
</body>
</html>
最终显示效果图:

原图:4.5M

 

压缩后图片:19K

 

上传文件效果图和目录结构:

 

上传完成:

 

服务端代码:

Controller层代码如下:

import com.sunlands.feo.common.util.FileCompress;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
* @author :冉野
* @date :Created in 2019-07-11 13:27
* @description:文件处理Controller
* @modified By:
* @version: 1.0.4$
*/
@Slf4j
@RestController
@RequestMapping("/file")
public class FileProcessController {

@ApiOperation("图片上传")
@PostMapping(value = "/upload")
public String upload(@RequestParam(name = "imageFile") MultipartFile imageFile) {

String filePath = FileCompress.thumbnail(imageFile, 0, 0, "");
log.info("图片存储路径:[{}]",filePath);
return filePath;

}
}
Java原生JDK压缩方式和Google工具类压缩和上传的两种方式:

package com.sunlands.feo.common.util;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.MultipartFile;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;


/**
* @author :冉野
* @date :Created in 2019-07-12 09:29
* @description:测试图片压缩 测试使用写博客用 需求背景说明 最近后端管理项目中需要用到用户一些证件图片进行表单文件的上传 如果每个人的证件照片都非常大,对服务器资源将是一种浪费,
* 因为用户量也不是很大,所以也没对接第三方的OSS或者七牛云存储对象,就写个简单的图像压缩吧,我主要是提供了两种方式进行图片压缩,第一种是使用Java自带的Image绘制图像,输入指定的宽高尺寸,最后
* 在重新绘制新的图片,核心代码也就三四行左右,压缩绘制算法都是JDK底层已经封装完成了。
* 第二种是使用Google的压缩工具类Thumbnails 大名鼎鼎的不一般,只需要一行代码即可,可实现的功能那是相当的丰富,图像指定宽高压缩,原图压缩,添加水印,图像旋转,指定图像压缩质量比例等等。
* @modified By:不要重复造轮子 不要重复造轮子 不要重复造轮子
* @version: 0.0.1$
*/
@Slf4j
public class ImageCompress {

// 这链接地址是拼接对应的服务器地址 用于回显给前端该图片地址使用。最后返回的效果是这样的:https://ucr.nb01.xyz/image-ucr/700393939333.png
// 前端通过该地址可在浏览器直接访问,需要说明一点是 图片上传在了/opt/image目录下,最后通过地址能访问到该图片,需要通过nginx做一层转发,具体那就是运维可以配置一下或者自己NGINX 配置一下。
private static final String PROD_URL = "";
private static final String TEST_URL = "https://ucr.nb01.xyz/image-ucr/";
private static final String LOCAL_URL = "http://127.0.0.1:8802/feo/";
// 用的MAC系统,所以直接放在了系统的根目录某个文件夹下 如果是Win系统也可指定在某个盘符下存储即可。
private static final String dirPath = "/opt/image";
// 方式一压缩
public static String imageCompress(MultipartFile file, int targetWidth, int targetHeight) {
long startTime = System.currentTimeMillis();
//得到上传时的原文件名
String originalFilename = file.getOriginalFilename();
//获取文件后缀名
String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
String imageType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
//通过系统时间戳来命名文件:不是非常的规范请勿模仿
String name = String.valueOf(System.nanoTime());
String saveName = name.concat(suffixName);
//存储目录
String savePath = UploadPathUtils.getPicUploadDir(targetWidth, targetHeight);
//图片存储全路径
String outputPath = savePath.concat("/").concat(saveName);
log.info("图片存储路径:[{}]",outputPath);
OutputStream fouts = null;
// 以上都是前期的准备
try {
//读取源图
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
// 获取源图宽度
double srcWidth = bufferedImage.getWidth();
// 获取源图高度
double srcHeight = bufferedImage.getHeight();
// 判断是否是需要压缩的尺寸比原图小 否则不进行压缩
if ((int) srcWidth >= targetWidth && (int) srcHeight >= targetHeight) {
// 建立传输通道---文件输出流 最后以流的形式把文件内容传输过去
fouts = new FileOutputStream(outputPath);
// 绘制新图时,使用Image.SCALE_SMOOTH算法,压缩后的图片质量相对比较光滑,没有明显的锯齿形,又叫做图片压缩光滑算法
// 还可选择其他压缩算法 例如:SCALE_FAST 比光滑算法更快速,还有默认算法等可选。
Image image = bufferedImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);
BufferedImage bufferedImage1 = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage1.getGraphics();
g.setColor(Color.RED);
//绘制处理后的图
g.drawImage(image, 0, 0, null);
g.dispose();
ImageIO.write(bufferedImage1, imageType, fouts);
log.info("图片压缩结束");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fouts != null) {
try {
fouts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (FileUtil.isLinux()) {
outputPath = TEST_URL.concat(saveName);
}
return outputPath;
}

/**
* 方式二压缩 Google大法 因为Thumbnails.of() 方法是一个重载方法,参数不仅仅局限于是一个文件类型 可以是以流的形式 File形式,ImageBuffer对象,URL路径,String类型指定文件路径
* 然后可通过链式构造器传入不通参数,压缩比例,指定输出的格式等最终通过toFile("文件存储路径")返回一个已经压缩完成的图片。
* @param file 待压缩的文件
* @return 压缩后图片路径 这个可自己指定
*/
public static String thumbnail(MultipartFile file) {
//得到上传时的原文件名
String originalFilename = file.getOriginalFilename();
//获取文件格式
String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
//获取uuid作为文件名
String name = UUID.randomUUID().toString().replaceAll("-", "");
try {
// 先尝试压缩并保存图片
Thumbnails.of(file.getInputStream()).scale(0.5f)
.outputQuality(0.15f)
.outputFormat("jpeg")
.toFile("/image/" + name);
} catch (IOException e) {

}
return TEST_URL.concat(name).concat(".").concat("jpeg");
}
}

 

标签:Springboot,压缩,String,file,import,上传,图片
From: https://www.cnblogs.com/fswhq/p/17686653.html

相关文章

  • 计算机毕业设计必看必学!! 85583 springboot高校网上选课系统,原创定制程序, java、PHP
                                                  摘要本论文主要论述了如何使用JAVA语言开发一个高校网上选课系统,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,......
  • SpringBoot-事件监听机制
    SpringBoot-事件监听机制  本文参考的SpringBoot版本是2.6.13  一、SpringBoot启动事件顺序 事件执行顺序: 1. ApplicationStartingEvent   springboot最开始启动时触发,SpringApplication.run()之前发送。 2.ApplicationEnvironm......
  • tomcat10 springboot项目部署成功但springboot没有启动日志问题
    问题描述项目在tomcat8可以启动成功,请求也可以正常处理,在tomcat10上只有部署成功信息比如:deployWARDeploymentofwebapplicationarchive[/data1/WWW/webapps/XXX.war]hasfinishedin[127]ms,但是没有springboot启动的信息。该问题不属于springboot打包为war包不成......
  • Springboot注解
    Springboot注解DAO、Service、Controller1、dao层dao层主要做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,dao层的设计首先是设计dao层的接口,然后在Spring的配置文件中定义此接口的实现类,dao层的数据源配置,以及有关数据库连接参数都在Spring配置文件中进行......
  • springboot自学(6)springboot核心原理
    Springboot启动流程初始化各种属性,加载成对象  读取环境属性(Environment)  系统配置(spring.factories)  参数(Arguments、application.properties)创建Spring容器对象ApplicationContext,加载各种配置在容器创建前,通过监听器机制,应对不同阶段加载数据、更新数据的要求......
  • 【漏洞复现】LiveBOS UploadFile.do 任意文件上传漏洞(XVE-2023-21708)
    0x01产品简介LiveBOS(LiveBusinessObjectSystem)是顶点软件自主研发的以业务对象建模为核心的业务中间件及其集成开发工具,它通过业务模型建立直接完成软件开发的创新模式,支持各类基于WEB的专业应用软件与行业大型应用的开发。LiveBOS系统由三个相对独立的产品构成:运行支......
  • mysql分区自动维护(SpringBoot+MybatisPlus)
    1.环境SpringBoot+MybatisPlus+MySQL2.简介通过定时器@Scheduled每日触发,查询当前库中所有分区表(这里以时间段进行分区)判断剩余分区是否小于自定义预留分区(无自定义预留分区则取默认分区配置),若小于预留分区时,自动创建分区至配置分区数判断已有分区是否大于自定义保留分......
  • springboot多数据源整合及使用(一个oracle,两个mysql)
    在开发工作中,会遇到需要使用多个数据源的情况,比如项目一开始只有oracle,后面需要追加两个mysql数据源使用,这时候就需要配置多数据源了.首先,配置文件的编写:版本如下spring:datasource:db1:driver-class-name:com.mysql.cj.jdbc.Driverurl:......
  • 免费【2024】springboot 大学校园旧物捐赠网站的设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......
  • 免费【2024】springboot 大学生家教管理系统的设计与实现
    博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数......