一,为什么要给图片生成缩略图?

1, 用户上传的原始图片如果太大,不能直接展示在网站页面上,

因为不但流费server的流量,而且用户打开时非常费时间,

所以要生成缩略图。

2,服务端管理图片要注意的几点:

第一点:缩略图要与原图分开存储,
   然后通过符号链接方式允许前端访问,

否则原图被直接访问仍然存在浪费流量的问题,

有图片版权的公司也不允许外部直接访问原图

第二点:图片名字要加上一些随机的数字,

避免被穷举访问

第三点:图片要分目录存放,通常每1000张保存到一个目录,

因为大量的图片如果存放到同一个目录下,

打开时会非常慢或者不能打开,

不利于我们对文件进行管理

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,项目的地址:

https://github.com/liuhongdi/imagemodify

2,项目原理:

实现了图片的文件上传,

并用ImageMagick给非gif图片生成缩略图,

用ffmpeg生成gif图片的缩略图

3,项目结构:如图:

三,ImageMagick/ffmpeg工具软件的安装

1,dnf安装ImageMagick

[root@blog head]# dnf install ImageMagick 

说明:注意软件包名字中I和M均为大写

检查软件是否安装成功?

[root@blog head]# whereis convert
convert: /usr/bin/convert /usr/share/man/man1/convert.1.gz

2,安装ffmpeg

安装rpmfusion库

[root@blog ~]# dnf install https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm 

下载sdl库

[root@blog ~]# wget http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/SDL2-2.0.8-7.el8.x86_64.rpm

安装sdl库:

[root@blog ~]# rpm -ivh SDL2-2.0.8-7.el8.x86_64.rpm
Verifying... ################################# [100%]
Preparing... ################################# [100%]
Updating / installing...
1:SDL2-2.0.8-7.el8 ################################# [100%]

安装ffmpeg

[root@blog ~]# dnf install ffmpeg 

四,配置文件说明:

1,application.properties

#upload
spring.servlet.multipart.maxFileSize=30MB
spring.servlet.multipart.maxRequestSize=30MB

说明:指定上传文件的最大限制,

默认大小是1M

2,nginx访问文件的host配置:file.conf

server {
listen 81;
server_name file.lhdtest.com;
root /data/file/html;
location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
root /data/file/html;
expires 24h;
}
index index.html;
access_log /data/logs/nginxlogs/file.access_log;
error_log /data/logs/nginxlogs/file.error_log;
}

3,Constant.java

    //图片从nginx访问时的host
public static final String IMAGES_URL_HOST = "http://127.0.0.1:81";
//默认原始图片的路径
public static final String IMAGES_ORIG_DIR = "/data/file/html/images";
//缩略图的文件路径
public static final String IMAGES_TMB_DIR = "/data/file/html/tmb";
//缩略图的长边长度
public static final String IMAGES_TMB_LONG = "300";
//分页显示时每页的显示数量
public static final int IMAGES_PAGE_SIZE = 5;
//ImageMagick命令的安装路径
public static final String IMAGEMAGICK_DIR = "/usr/bin";
//ffmpeg的完整路径
public static final String FFMPEG_CMD = "/usr/bin/ffmpeg";

4,创建保存图片信息的数据表:

CREATE TABLE `image_service` (
`image_id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '图片id',
`image_sn` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '图片编号',
`image_type` varchar(10) NOT NULL DEFAULT '' COMMENT '图片类型',
`title` varchar(200) NOT NULL DEFAULT '' COMMENT '标题',
`size` int(11) NOT NULL DEFAULT '0' COMMENT '文件大小',
`width` int(11) NOT NULL DEFAULT '0' COMMENT '宽度',
`height` int(11) NOT NULL DEFAULT '0' COMMENT '高度',
`add_time` datetime NOT NULL DEFAULT '2019-11-01 01:01:01' COMMENT '添加时间 ',
`staff_id` int(11) NOT NULL DEFAULT '0' COMMENT '添加的用户',
PRIMARY KEY (`image_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='图片信息表'

五,java代码说明:

1,ImageModifyUtil.java

public class ImageModifyUtil {
//按指定的边长生成缩略图
public static boolean image_resize_by_long_side(String orig_path, String dest_path, String long_size,String imageType) {
try {
List<String> command = new ArrayList<>();
String command_one = "";
if (imageType.equals("gif")) {
//计算得到目标宽高
File gifFile = new File(orig_path);
int gifWidth = 0;
int gifHeight = 0;
try {
BufferedImage imageBuffer = ImageIO.read(gifFile);
if (imageBuffer != null) {//如果image=null 表示上传的不是图片格式
gifWidth = imageBuffer.getWidth();
gifHeight = imageBuffer.getHeight();
}
} catch (IOException e) {
e.printStackTrace();
}
int destWidth = 0;
int destHeight = 0;
if (gifWidth > gifHeight) {
destWidth = Integer.parseInt( long_size );
destHeight = (destWidth*gifHeight) / gifWidth;
} else if (gifWidth == gifHeight) {
destWidth = Integer.parseInt( long_size );
destHeight = destWidth;
} else {
destHeight = Integer.parseInt( long_size );
destWidth = (destHeight*gifWidth) / gifHeight;
}
command_one = Constant.FFMPEG_CMD+" -i "+orig_path+" -s "+destWidth+"x"+destHeight+" "+dest_path+" 2>&1";
} else {
command_one = Constant.IMAGEMAGICK_DIR+"/convert -size "+long_size+"x"+long_size+" -resize "+long_size+"x"+long_size+" +profile '*' -quality 85 "+orig_path+" "+dest_path+" 2>&1";
}
//System.out.println(command_one);
command.add("sh");
command.add("-c");
command.add(command_one);
// 执行cmd命令
ProcessBuilder builder = new ProcessBuilder();
builder.command(command);
Process process = builder.start();
return true;
} catch (Exception e) {
System.out.println("save ioexception");
e.printStackTrace();
return false;
}
}
}

这个类用来生成缩略图

说明:gif图生成缩略图时,我们要帮助ffmpeg计算出准确的长和宽

2,ImageDownUtil.java

public class ImageDownUtil {
//按指定的路径下载一张图片
public static void downImageByLocalPath(HttpServletResponse response,String fullImagePath,String imageName) {
File file = new File(fullImagePath);
if (file.exists()) {
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + imageName);// 设置文件名
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
System.out.println("success");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
} //按指定的文件路径显示图片
public static ResponseEntity<InputStreamResource> dispImageByLocalPath(String fullImagePath) {
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.IMAGE_JPEG);
Path path = Paths.get(fullImagePath);
InputStream content;
try {
content = Files.newInputStream(path);
return new ResponseEntity<>(new InputStreamResource(content), header, HttpStatus.OK);
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.notFound().build();
}
}
}

这个类用来下载图片和用java显示一张图片

六,效果测试

测试前的注意事项:

测试前要先启动服务:

mysql

nginx

1,图片上传:

访问:

http://127.0.0.1:8080/image/imageadd

如图:

2,查看已上传的图片列表

访问:

http://127.0.0.1:8080/image/imagelist

如图:

七,查看spring boot的版本

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.1.RELEASE)

spring boot:实现图片文件上传并生成缩略图(spring boot 2.3.1)的更多相关文章

  1. tp3.2 自带的文件上传及生成缩略图功能

    public function upload_file($file_name,$width,$height) { //检查图片尺寸是否合法 $image_size = getimagesize($_F ...

  2. CI自带的文件上传及生成缩略图

    /* * 文件上传 * @param $upload_path 文件上传路径 * @param $formpic 表单name属性名称 */ private function doUpload($up ...

  3. Office文件上传自动生成缩略图

    来源:微信公众号CodeL 前不久产品经理提出一个X的需求,说上传office文件的时候需要将首页自动截图,用于显示文件列表的时候将文件第一页缩略图展示给用户.实现的方式有多种,这里给大家介绍一个简单 ...

  4. Office文件上传自动生成缩略图-C#开发

    原文: http://www.knowsky.com/898407.html 上传office文件的时候需要将首页自动截图,用于显示文件列表的时候将文件第一页缩略图展示给用户.实现的方式有多种,这里给 ...

  5. Spring中MultipartHttpServletRequest实现文件上传

    Spring中MultipartHttpServletRequest实现文件上传 转贴自:http://my.oschina.net/nyniuch/blog/185266 实现图片上传  用户必须能 ...

  6. spring mvc 简单的文件上传与下载

    上传文件有很多种方法,这里主要讲解的是spring mvc内提供的文件上传 前提使用:spring mvc 在这个之前我们需要把环境给配置好 1:springmvc的XML配置文件加上这一段就即可, ...

  7. 利用spring的MultipartFile实现文件上传【原】

    利用spring的MultipartFile实现文件上传 主要依赖jar包 spring-web-3.0.6.RELEASE.jar 用到 (org.springframework.web.multi ...

  8. springmvc图片文件上传接口

    springmvc图片文件上传 用MultipartFile文件方式传输 Controller package com.controller; import java.awt.image.Buffer ...

  9. SpringMvc MultipartFile 图片文件上传

    spring-servlet.xml <!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 --> <bean id="multipar ...

随机推荐

  1. linux系统漏洞扫描工具lynis

    lynis 是一款运行在 Unix/Linux 平台上的基于主机的.开源的安全审计软件.Lynis是针对Unix/Linux的安全检查工具,可以发现潜在的安全威胁.这个工具覆盖可疑文件监测.漏洞.恶意 ...

  2. SpringCloud实战 | 第四篇:SpringCloud整合Gateway实现API网关

    一. 前言 微服务实战系列是基于开源微服务项目 有来商城youlai-mall 版本升级为背景来开展的,本篇则是讲述API网关使用Gateway替代Zuul,有兴趣的朋友可以进去给个star,非常感谢 ...

  3. MySQL<=>是什么鬼

    官网描述 NULL-safe equal. This operator performs an equality comparison like the = operator, but returns ...

  4. hystrix源码小贴士之Servo Publisher

    HystrixServoMetricsPublisher 继承HystrixMetricsPublisher,创建HystrixServoMetricsPublisherCommand.Hystrix ...

  5. Volatile禁止指令重排序(三)

    Volatile禁止指令重排 计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令重排,一般分为以下三种: 源代码 -> 编译器优化的重排 -> 指令并行的重排 -> 内存系 ...

  6. shiro-重写标签功能----shiro:hasPermission 标签重写

    public abstract class ShiroAuthorizingRealm extends AuthorizingRealm{ private static final String OR ...

  7. luogu2756 飞行员配对方案问题 (裸匈牙利)

    匈牙利: 4 81 51 62 53 53 74 54 74 8-1 -1 out:4 #include<iostream> #include<cstdio> #include ...

  8. 基于Java反射的定时任务设计

    一.使用场景 1.不需要立即执行.立即得到结果返回. 2.如果执行失败.需要有失败补偿机制. 3.和业务代码解耦,适用于不同的务场景. 4.调用接口的入参.出参 统计,方便查询. 二.执行顺序 1.业 ...

  9. 双向最大匹配算法——基于词典规则的中文分词(Java实现)

    目录 一.中文分词理论描述 二.算法描述 1.正向最大匹配算法 2.反向最大匹配算法 3.双剑合璧 三.案例描述 四.JAVA实现完整代码 五.组装UI 六.总结 前言 这篇将使用Java实现基于规则 ...

  10. Java单播、组播(多播)、广播的简单实现

    简介 单播有TCP和UDP两种实现,组播(多播)和广播只有UDP一种实现.单播和广播基本一样,只是广播的数据包IP为广播IP.   单播 DatagramSocket和DatagramPacket 服 ...