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

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 等等)
| 序号 | 字段名称 | 字段类型 | 字段说明 |
|---|---|---|---|
| 1 | id | varchar(50) | 主键 |
| 2 | code | varchar(50) | 类型编号(如:document) |
| 3 | name | varchar(50) | 类型名称(如:文档、图片、视频、音频、其他) |
对应的数据展示如下:
| id | code | name |
|---|---|---|
| 001 | document | 文档 |
| 002 | picture | 图片 |
| 003 | video | 视频 |
**disk_type_suffix:**类型-对应的格式明细表
| 序号 | 字段名称 | 字段类型 | 字段说明 |
|---|---|---|---|
| 1 | id | varchar(50) | 主键 |
| 2 | typecode | varchar(50) | 所属编号,对应disk_type的code |
| 3 | name | varchar(50) | 后缀名称(如:word) |
| 4 | icon | longtext | 32*32图标base64字符串 |
| 5 | iconbig | longtext | 128*128图标base64字符串 |
| 6 | suffix | varchar(50) | 后缀格式(如:doc/docx) |
对应的数据展示如下:
| id | typecode | name | suffix | icon | iconbig |
|---|---|---|---|---|---|
| 001 | document | word | doc | xxx | xxx |
| 002 | document | word | docx | xxx | xxx |
思考:把图标放到数据库,会不会影响性能呢?
把图标转换字符串(不是 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...




