图片上传 mongo + get请求带 token 预览 图片 生成gif动图
<!-- 图片转gif动图 -->
<dependency>
<groupId>com.madgag</groupId>
<artifactId>animated-gif-lib</artifactId>
<version>1.4</version>
</dependency>
<!-- mogodb 的支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
controller层
import cn.hutool.core.convert.Convert;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* <p>
* 图片上传和预览控制器
* </p>
*
*/
@RestController
@RequestMapping("/image/upload")
@Api(value = "图片上传和预览controller", tags = {"图片上传和预览接口"})
public class ImageUploadController {
@Autowired
private ImageUploadService imageUploadService;
@ApiOperation(value = "图片上传", notes = "图片上传上传", httpMethod = "POST")
@PostMapping("/image/upload")
public String imageUpload(@RequestParam("file") MultipartFile file){
return this.imageUploadService.imageUpload(file);
}
@ApiOperation(value = "基层数据查询成果预览", notes = "基层数据查询成果预览", httpMethod = "GET")
@ApiImplicitParam(name = "imageid", value = "图片存mongo中的id", required = true, dataType = "String")
@GetMapping("/image/{imageid}/preview.png")
public byte[] previewPng(@RequestParam("imageid")String imageid){
return this.imageUploadService.previewPng(imageid);
}
}
service 层
import com.baomidou.mybatisplus.extension.service.IService;
import com.sgis.one.map.micro.analysis.model.entity.TMicroAchievement;
import com.sgis.one.map.micro.analysis.model.vo.SelectMicroAchievementVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* <p>
* 图片上传和预览服务类
* </p>
*/
public interface ImageUploadService extends IService<entityTable> {
/**
* 图片上传
* @param file
* @return 图片存入mongo中的ObjectId
*/
String imageUpload(MultipartFile file);
/**
* 图片预览
* @param imageid 图片存入mongo中的ObjectId
* @return 图片的二进制流
*/
byte[] previewPng(String imageid);
}
Impl层
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sgis.common.file.util.MongoService;
import com.sgis.common.handler.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* <p>
* 图片上传和预览实现类
* </p>
*/
@Service
public class ImageUploadServiceImpl extends ServiceImpl<entityMapper, entityTable> implements ImageUploadService {
@Autowired
private MongoService mongoService;
/**
* 图片上传
* @param file
* @param userId
* @param fsgisOneMapMacroAnalysis
* @return
*/
@Override
public String imageUpload(MultipartFile file, Integer userId, String serviceId) {
BufferedImage read = null;
try {
read = ImageIO.read(file.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
if (read == null){
throw new BusinessException(500,"图片格式不正确");
}
String fileName = file.getOriginalFilename();
return this.mongoService.uploadFile(file);
}
/**
* 图片预览
* @param imageid
* @return
*/
@Override
public byte[] previewPng(String imageid) {
return this.mongoService.downloadImageByte(imageid, null);
}
}
mongoService
import cn.hutool.core.util.ObjectUtil;
import com.madgag.gif.fmsware.AnimatedGifEncoder;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import org.apache.commons.io.IOUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
/**
*@program:
*@description: MongoService
*/
@Service
public class MongoService {
@Autowired
private GridFsTemplate gridFsTemplate;
@Autowired
private MongoDbFactory mongoDbFactory;
/**
* 保存到本地
* @param fileId
* @param path
* @param fileName
* @throws Exception
*/
public void downloadToLocal(String fileId,String path,String fileName) throws Exception {
try {
//查询单个文件
Query query = Query.query(Criteria.where("_id").is(fileId));
GridFSFile gfsFile = gridFsTemplate.findOne(query);
if (gfsFile == null) {
return;
}
GridFSBucket gridFSBucket= GridFSBuckets.create(mongoDbFactory.getDb());
GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gfsFile.getObjectId());
//创建GridFsResource对象,获取流
GridFsResource gridFsResource = new GridFsResource(gfsFile, gridFSDownloadStream);
FileOutputStream downloadFile = new FileOutputStream(path + File.separator + fileName);
IOUtils.copy(gridFsResource.getInputStream(),downloadFile);
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件上传到mongo服务器上
* @param multipartFile 文件
* @param fileName 存入mongo中的名字
* @return
* @throws Exception
*/
public ApiResult<FileInfo> uploadFile(MultipartFile multipartFile,String fileName) throws Exception{
//查看mongo中是否已经保存图片
Query filename = Query.query(Criteria.where("filename").is(fileName));
GridFSFile one = this.gridFsTemplate.findOne(filename);
if (ObjectUtil.isNotNull(one)){
Query deleteQuery = Query.query(Criteria.where("_id").is(one.getId()));
this.gridFsTemplate.delete(deleteQuery);
}
// 获得文件输入流
InputStream fileIn = multipartFile.getInputStream();
// 将文件存储到mongodb中,mongodb 将会返回这个文件的具体信息
ObjectId objectId = gridFsTemplate.store(fileIn,fileName);
return objectId.toString();
}
/**
* GIF动图预览
* @param queryid gif动图的唯一标识
* @param path gif动图保存路径
* @param time gif动图间隔时间
* @param isCompress 图片是否压缩
* @param ratio 压缩比例
* @return
* @throws IOException
*/
public byte[] downloadGifByte(String queryid, String path, Integer time, Boolean isCompress, Integer ratio) throws IOException {
//匹配mongo中filename满足以queryid开头的文件
String regex = queryid + "([\\s\\S]*?)";
Query filename = Query.query(Criteria.where("filename").regex(regex));
GridFSFindIterable gridFSFiles = gridFsTemplate.find(filename);
InputStream inputStream = null;
//gif动图创建的类
AnimatedGifEncoder animatedGifEncoder = new AnimatedGifEncoder();
animatedGifEncoder.setRepeat(0);
//动图保存地址
String gifPath = path + "/" + queryid + ".gif";
//压缩图片保存的地址
String saveFile = path + "/" + queryid + ".png";
animatedGifEncoder.start(gifPath);
//gif动图返回的二进制流
byte[] fileBytes=null;
for (GridFSFile gfsFile : gridFSFiles) {
if (ObjectUtil.isNotNull(gfsFile)) {
GridFSBucket gridFSBucket = GridFSBuckets.create(mongoDbFactory.getDb());
GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gfsFile.getObjectId());
//创建GridFsResource对象,获取流
GridFsResource gridFsResource = new GridFsResource(gfsFile, gridFSDownloadStream);
inputStream = gridFsResource.getInputStream();
BufferedImage image = null;
if (!isCompress){
JPEGImageDecoder decoderFile = JPEGCodec.createJPEGDecoder(inputStream);
image = decoderFile.decodeAsBufferedImage();
} else
//压缩图片,压缩图不保存到本地
{
image = ImageHelper.compress(inputStream, new File(saveFile), ratio);
}
animatedGifEncoder.setDelay(time);
animatedGifEncoder.addFrame(image);
}
}
animatedGifEncoder.finish();
FileInputStream fileInputStream = new FileInputStream(gifPath);
转化inputStream 为byte[]
fileBytes= is2ByeteArray(fileInputStream);
inputStream.close();
return fileBytes;
}
/**
* 图片预览
* @param fileId
* @param defaultStream
* @return
*/
public byte[] downloadImageByte(String fileId) {
byte[] fileBytes=null;
try {
// 查询单个文件
Query query = Query.query(Criteria.where("_id").is(fileId));
GridFSFile gfsFile = gridFsTemplate.findOne(query);
InputStream inputStream = null;
if (ObjectUtil.isNotNull(gfsFile)) {
GridFSBucket gridFSBucket = GridFSBuckets.create(mongoDbFactory.getDb());
GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gfsFile.getObjectId());
//创建GridFsResource对象,获取流
GridFsResource gridFsResource = new GridFsResource(gfsFile, gridFSDownloadStream);
inputStream = gridFsResource.getInputStream();
}
fileBytes= is2ByeteArray(inputStream);
inputStream.close();
}catch (Exception e){
e.printStackTrace();
}
return fileBytes;
}
//转化inputStream 为byte[]
public byte[] is2ByeteArray(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc = 0;
while((rc=is.read(buff, 0, 100))>0) {
baos.write(buff, 0, rc);
}
return baos.toByteArray();
}
}
图片压缩工具类 ImageHelper
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
/**
* @author: Supermap·F
* @descripition: 图片压缩
* @date: created in 11:05 2020/8/19
* @modify: Copyright (c) Supermap All Rights Reserved.
*/
public class ImageHelper {
/**
* 实现图像的等比缩放
* @param source
* @param targetW
* @param targetH
* @return
*/
private static BufferedImage resize(BufferedImage source, int targetW,
int targetH) {
// targetW,targetH分别表示目标长和宽
int type = source.getType();
BufferedImage target = null;
double sx = (double) targetW / source.getWidth();
double sy = (double) targetH / source.getHeight();
// 这里想实现在targetW,targetH范围内实现等比缩放。如果不需要等比缩放
// 则将下面的if else语句注释即可
if (sx < sy) {
sx = sy;
targetW = (int) (sx * source.getWidth());
} else {
sy = sx;
targetH = (int) (sy * source.getHeight());
}
if (type == BufferedImage.TYPE_CUSTOM) { // handmade
ColorModel cm = source.getColorModel();
WritableRaster raster = cm.createCompatibleWritableRaster(targetW,
targetH);
boolean alphaPremultiplied = cm.isAlphaPremultiplied();
target = new BufferedImage(cm, raster, alphaPremultiplied, null);
} else
target = new BufferedImage(targetW, targetH, type);
Graphics2D g = target.createGraphics();
// smoother than exlax:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
g.dispose();
return target;
}
/**
* 实现图像的等比缩放和缩放后的截取, 处理成功返回true, 否则返回false
* @param inFilePath 要截取文件的路径
* @param outFilePath 截取后输出的路径
* @param width 要截取宽度
* @param hight 要截取的高度
* @throws Exception
*/
public static BufferedImage compress(String inFilePath, String outFilePath,
int width, int hight) {
BufferedImage ret = null;
File file = new File(inFilePath);
File saveFile = new File(outFilePath);
InputStream in = null;
try {
in = new FileInputStream(file);
ret = compress(in, saveFile, width, hight);
} catch (FileNotFoundException e) {
e.printStackTrace();
ret = ret;
} finally{
if(null != in){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ret;
}
/**
* 实现图像的等比缩放和缩放后的截取, 处理成功返回true, 否则返回false
* @param in 要截取文件流
* @param saveFile 截取后输出的路径
* @param width 要截取宽度
* @param hight 要截取的高度
* @throws Exception
*/
public static BufferedImage compress(InputStream in, File saveFile,
int width, int hight) {
// boolean ret = false;
BufferedImage srcImage = null;
BufferedImage resultImage = null;
try {
srcImage = ImageIO.read(in);
} catch (IOException e) {
e.printStackTrace();
return resultImage;
}
if (width > 0 || hight > 0) {
// 原图的大小
int sw = srcImage.getWidth();
int sh = srcImage.getHeight();
// 如果原图像的大小小于要缩放的图像大小,直接将要缩放的图像复制过去
if (sw > width && sh > hight) {
srcImage = resize(srcImage, width, hight);
} else {
String fileName = saveFile.getName();
String formatName = fileName.substring(fileName
.lastIndexOf('.') + 1);
try {
ImageIO.write(srcImage, formatName, saveFile);
} catch (IOException e) {
e.printStackTrace();
return resultImage;
}
return resultImage;
}
}
// 缩放后的图像的宽和高
int w = srcImage.getWidth();
int h = srcImage.getHeight();
// 如果缩放后的图像和要求的图像宽度一样,就对缩放的图像的高度进行截取
if (w == width) {
// 计算X轴坐标
int x = 0;
int y = h / 2 - hight / 2;
try {
resultImage = saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return resultImage;
}
}
// 否则如果是缩放后的图像的高度和要求的图像高度一样,就对缩放后的图像的宽度进行截取
else if (h == hight) {
// 计算X轴坐标
int x = w / 2 - width / 2;
int y = 0;
try {
resultImage = saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return resultImage;
}
}
return resultImage;
}
/**
* 实现图像的等比缩放和缩放后的截取, 处理成功返回true, 否则返回false
* @param in 图片输入流
* @param saveFile 压缩后的图片输出流
* @param proportion 压缩比
* @throws Exception
*/
public static BufferedImage compress(InputStream in, File saveFile, int proportion) {
if(null == in || null == saveFile || proportion < 1){// 检查参数有效性
//LoggerUtil.error(ImageHelper.class, "--invalid parameter, do nothing!");
return null;
}
BufferedImage srcImage = null;
BufferedImage resultImage = null;
try {
srcImage = ImageIO.read(in);
} catch (IOException e) {
e.printStackTrace();
return resultImage;
}
// 原图的大小
int width = srcImage.getWidth() / proportion;
int hight = srcImage.getHeight() / proportion;
srcImage = resize(srcImage, width, hight);
// 缩放后的图像的宽和高
int w = srcImage.getWidth();
int h = srcImage.getHeight();
// 如果缩放后的图像和要求的图像宽度一样,就对缩放的图像的高度进行截取
if (w == width) {
// 计算X轴坐标
int x = 0;
int y = h / 2 - hight / 2;
try {
resultImage = saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return resultImage;
}
}
// 否则如果是缩放后的图像的高度和要求的图像高度一样,就对缩放后的图像的宽度进行截取
else if (h == hight) {
// 计算X轴坐标
int x = w / 2 - width / 2;
int y = 0;
try {
resultImage = saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return resultImage;
}
}
return resultImage;
}
/**
* 实现缩放后的截图
* @param image 缩放后的图像
* @param subImageBounds 要截取的子图的范围
* @param subImageFile 要保存的文件
* @throws IOException
*/
private static BufferedImage saveSubImage(BufferedImage image, Rectangle subImageBounds, File subImageFile) throws IOException {
if (subImageBounds.x < 0 || subImageBounds.y < 0
|| subImageBounds.width - subImageBounds.x > image.getWidth()
|| subImageBounds.height - subImageBounds.y > image.getHeight()) {
//LoggerUtil.error(ImageHelper.class, "Bad subimage bounds");
return null;
}
BufferedImage subImage = image.getSubimage(subImageBounds.x,subImageBounds.y, subImageBounds.width, subImageBounds.height);
//暂时不用写在服务器本地
// String fileName = subImageFile.getName();
// String formatName = fileName.substring(fileName.lastIndexOf('.') + 1);
// ImageIO.write(subImage, formatName, subImageFile);
return image;
}
}
图片预览测试
百度图片 - 动图 (任何一个有图片或者动图的网站)

http://localhost:端口/******/image/{imageid}/preview.png?imageid=图片存入mongo中返回的id&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJmaXNoZXIiLCJzY29wZSI6WyJzZXJ2ZXIiXSwiZXhwIjoxNTk3Nzc1MDkyLCJ1c2VyTmFtZSI6ImZpc2hlciIsInVzZXJJZCI6NTAsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJQRVJfU1VQRVJBRE1
access_token= token信息
替换图片中的地址,就可以直接预览图片
参考链接:
图片转gif动图
https://www.cnblogs.com/myjoan/p/4739102.html
https://blog.csdn.net/qq_35350654/article/details/83446258
图片压缩
https://my.oschina.net/u/242764/blog/2980538

浙公网安备 33010602011771号