spring boot:实现图片文件上传并生成缩略图(spring boot 2.3.1)

时间:2022-12-30 10:48:40

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

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,项目结构:如图:

spring boot:实现图片文件上传并生成缩略图(spring boot 2.3.1)

三,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

如图:

spring boot:实现图片文件上传并生成缩略图(spring boot 2.3.1)

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

访问:

http://127.0.0.1:8080/image/imagelist

如图:

spring boot:实现图片文件上传并生成缩略图(spring boot 2.3.1)

七,查看spring boot的版本

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

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

  1. tp3&period;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&num;开发

    原文: 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用户不在sudoers文件中

    *** is not in the sudoers file.  This incident will be reported."  (用户不在sudoers文件中--) 处理这个问题很简单 ...

  2. 2016HUAS&lowbar;ACM暑假集训2J - 今年暑假不AC

    简单的贪心题.把节目的结束时间按升序排列,从第一个节目开始,寻找可以完全看完的节目. 这里用了结构体,所以要自己写排序方式. 总之,贪心的第一要义就是——排序! 本人新手,请体谅. #include& ...

  3. H5神器之canvas应用——网页修改保存图片

    因为最近项目上的要求,需要在页面中可以对一张图片进行涂改和添加文字,然后再保存到(服务器)本地,因为也是第一次接触这方面的,然后爬网页啊爬网页,之后发现了一款adobe开发的一款插件,适合 Anroi ...

  4. 【leetcode】Longest Palindromic Substring &lpar;middle&rpar; 经典

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  5. vs之Nuget

    1.http://msdn.microsoft.com/zh-cn/magazine/hh547106.aspx 2.在Nuget控制台中安装特定版本: Install-Package <程序包 ...

  6. makefile 进阶

    一步一步写一个简单通用的makefile(一) 一步一步写一个简单通用的makefile(二) 一步一步写一个简单通用的makefile(三) 一步一步写一个简单通用的makefile(四)

  7. CDOJ 1270 Playfair

    模拟题,代码写得比较乱... #include<cstdio> #include<cstring> #include<cmath> #include<queu ...

  8. Docker学习笔记 - Docker客户端和服务端

    学习内容: Docker客户端和服务端的通讯方式:client和自定义程序 Docker客户端和服务端的连接方式:socket 演示Docker客户端和服务端之间用remote-api通讯:nc   ...

  9. spring配置遇到的问题

    1.文档根元素 "beans" 必须匹配 DOCTYPE 根 "null" 这个原因是因为我自动扫描mapping.xml的文件路径设置错误,把它设置成spri ...

  10. Mysql 和 Postgresql&lpar;PGSQL&rpar; 对比

    Mysql 和 Postgresql(PGSQL) 对比 转载自:http://www.oschina.net/question/96003_13994 PostgreSQL与MySQL比较 MySQ ...