暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

微服务专栏(二十):文件图标的设计及开发

修电脑的杂货店 2021-12-08
696

 立志是事业的大门,工作是登堂入室的旅程。——巴斯德


1、业务需求

想实现不同格式的文件,在页面展示的时候,展示不同的文件图标,让用户看起来比较舒服一点,具体需求如下:

  • 第一:不同格式的文件,则展示不同的图标,比如:doc 和 txt 展示的是两种不同的图标。

  • 第二:文件展示有两种不同的方式,分别是列表和卡片式,那么这种不同展现方式对应图标的大小不一样。

效果图如下所示


2、功能设计

我相信需求还是比较简单易于理解的,但是如何实现这样的需求,很多同学或许有点不懂怎么实现了。很多人会通过静态文件的模式去实现,具体做法如下:

  • 第一:事先准备好常用的图标,两种不同尺寸的图标,把这些图标分别放在前端工程的 images_small 和 images_big 目录下面。

  • 第二:列表展示的时候,在前端代码里面 if 判断调用哪个图标做展示。

  • 这种做法很简单,但是扩展性不好,如果用户上传的文件事先没有准备其图标,则无法展示。还有一个致命的弊端就是,如果格式种类很多那么 if 判断很多;如果很多个列表都需要展示文件列表(展示图标),那么需要在很多的地方进行判断。但是我发现既然很多人都是这么去做的(我看过别的项目就是这种模式)。

其实解决方案很简单,就是在后台系统新增一个文件图标管理模块即可,具体效果图如下所示:

实现思路梳理

  • ① 对文件进行分类,主要分为:文档、图片、音频、视频、其他

  • ② 每种类型,又对应不同的文件格式
    (比如:文档主要有 doc/docx/xls/xlsx/txt 等等、图片主要有 jpg/png 等等)

  • ③ 每种格式有分别对应两个图标,分别是 32px 和 64px

  • ④ 文件上传,根据文件格式
    查询其所属类型,保存到disk_file
    表的typecode
    字段

  • ⑤ 文件展示,根据文件格式
    查询其对应图标,主要是通过 sql 子查询关联出来

这种模式的优点如下

  • ① 可以很方便的在后台系统动态维护文件图标,如果碰到不存在的文件则手工上传即可

  • ② 对系统也算是一种保护,限制某些文件的上传(比如:exe等),文件上传的时候判断格式是否存在,不存在则提示联系管理员(现在回过头去看文件切块上传
    里面提到的格式放缓存,应该明白其用意了吧)


4、表结构设计

**disk_type:**文件类型表(比如:图片-picture,文档-document 等等)

序号字段名称字段类型字段说明
1idvarchar(50)主键
2codevarchar(50)类型编号(如:document)
3namevarchar(50)类型名称(如:文档、图片、视频、音频、其他)

对应的数据展示如下:

idcodename
001document文档
002picture图片
003video视频

**disk_type_suffix:**类型-对应的格式明细表

序号字段名称字段类型字段说明
1idvarchar(50)主键
2typecodevarchar(50)所属编号,对应disk_type的code
3namevarchar(50)后缀名称(如:word)
4iconlongtext32*32图标base64字符串
5iconbiglongtext128*128图标base64字符串
6suffixvarchar(50)后缀格式(如:doc/docx)

对应的数据展示如下:

idtypecodenamesuffixiconiconbig
001documentworddocxxxxxx
002documentworddocxxxxxxx

思考:把图标放到数据库,会不会影响性能呢?

  • 把图标转换字符串(不是 blob 字段,是 longtext 字段)存储数据库,可以防止图标丢失,方便系统迁移等

  • 尺寸为32*32
    的图标大小一般是几B,128*128
    的大小一般是几百B以下,其实相当于普通的字符串而已,文件的格式常见的无非几十种,所以存数据库是最好的选择

  • 这两个尺寸值是分别符合前端网盘列表展示
    卡片式展示
    的尺寸要求,如果列表模式和卡片式模式用同一张图标在前端使用 width 和 height 控制的话,图片效果是模糊的

  • disk_type_suffix
    数据量不会很大,因此不会占用太多的数据库资源


3、功能实现

**第一步:**项目结构及相关类

netdisk-web-manage
|-- com.micro.controller
| |-- TypeController.java //文件类型管理
| |-- TypeSuffixController.java //类型对应格式管理

netdisk-service-api
|-- com.micro.disk.service
| |-- TypeService.java //文件类型接口
| |-- TypeSuffixService.java //文件格式接口

netdisk-service-provider
|-- com.micro.service.impl
| |-- TypeServiceImpl.java //文件类型实现
| |-- TypeSuffixServiceImpl.java //文件格式实现

工程简单说明

  • 文件类型、格式、图标管理主要在网盘后台系统进行管理,因此新建disk-web-manage
    工程

  • TypeController
    类,主要是文件类型
    的增删改查(比如:文档、图片、视频、音频、其他)

  • TypeSuffixController.java
    类,主要是管理每种文件类型
    对应的文件格式
    图标

  • TypeService.java
    类,主要是文件类型
    的接口

  • TypeSuffixService.java
    类,主要是文件格式
    文件图标
    的接口

第二步:核心业务点解析

  • 新增一种文件格式
    的代码实现

@RestController
@RequestMapping("/typesuffix")
public class TypeSuffixController {
@Reference(check=false,filter={"logFilter"})
private TypeSuffixService tss;

/*
* typecode:格式所属类型(比如:文档)
* name:格式对应的文件名称(比如:word)
* suffix:格式的名称(比如:doc)
* file:32尺寸的图标
* filebig:64尺寸的图标
*/

@RequestMapping("/save")
public Result save(String typecode,String name,String suffix,MultipartFile file,MultipartFile filebig){
try{
String icon="";
String iconbig="";
String filename=file.getOriginalFilename();
String filenamebig=filebig.getOriginalFilename();

//32*32图标转换字符串
if(file!=null){
icon=getIconStr(filename, file.getBytes(),32);
}
//128*128图标转换字符串
if(filebig!=null){
icon=getIconStr(filenamebig, filebig.getBytes(),128);
}

tss.save(typecode, name, icon, iconbig, suffix, operatecodes);
return ResultUtils.success("添加成功", null);
}catch(Exception e){
return ResultUtils.error(e.getMessage());
}
}

private String getIconStr(String filename,byte[] bytes,int size){
//控制尺寸
if(!filename.endsWith(".png")){
throw new RuntimeException("图标必须是.png格式");
}
InputStream input=new ByteArrayInputStream(bytes);
BufferedImage sourceImg=ImageIO.read(input);
int width=sourceImg.getWidth(); //获取图标的宽
int height=sourceImg.getHeight(); //获取图标的高

if(width!=size||height!=size){
throw new RuntimeException("图标尺寸必须是"+size+"*"+size);
}
input.close();

//转换base64
String icon=Base64.encodeBase64String(bytes);
return icon;
}
}

  • 核心1:获取图标的宽和高,然后判断是否符合规范

  • 核心2:通过把 Base64 把图片转换字符串

第三步:文件展示的时候如何关联图标并且做展示

sql语句查询

select df.*,
/*关联图标字符串*/
(select icon from disk_type_suffix where suffix=df.filesuffix) as fileicon
from
disk_file df
where
df.createuserid=?

第四步:前端如何展示base64字符串

<img v-for="item in files" src="data:image/png;base64,{{item.fileicon}}" />


4、小结

本节的内容相对比较简单,但是思路比较重要,我们要学会把功能给做活了,而不是追求功能的实现即可,导致很多的硬编码给后期系统扩展带来非常大的麻烦。希望大家把这种思想掌握并且灵活的运用于自己的项目。

纸上得来终觉浅,绝知此事要coding...

文章转载自修电脑的杂货店,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论