文件上传组件
文件上传组件对el-upload进行了封装,来丰富文件的上传,上传文件列表管理,文件小图标识别等功能。
1、使用方法
上传组件使用时需要先import引用,之后就可以直接使用 waf-file-upload ,传递相应的参数即可使用
<!-- 上传组件使用-->
<waf-file-upload ref="fileUpload" :countLimit="countLimit" :sizeLimit="sizeLimit" :tip="tip"
:allowUpload="allowUpload" :allowDrag="allowDrag" :allowDowload="allowDowload" :initFileList="initFileList" :accept="accept">
// script 示例代码(详细参照waf-web中src/views/demo/FileUpload.vue)
import WafFileUpload from '@/components/Upload'
data() {
return {
// 上传文件数量限制(默认5个)
countLimit: 5,
// 上传文件大小限制(默认50M)
sizeLimit: 50 * 1024 * 1024,
// 初始化时的文件列表(用于修改时回显文件列表)
initFileList: [
{ uploadId:'2cfce53e1a724150998a93d3e40a290f',name:'SystemOut.log',type:'application/octet-stream'},
{uploadId:'74ce2a03316d47b58054b968ddb0ca94',name:'阿里巴巴Java开发手册.pdf',type:'application/pdf'}
],
fileList: [],
// 限制上传文件后缀(默认不限制)
accept: '.jpg,.jpeg,.png,.gif,.bmp,.pdf',
// 是否允许上传(默认true)
allowUpload: true,
// 是否允许下载(默认true)
allowDowload: true,
// 是否使用拖动文件上传(默认false)
allowDrag: false,
tip: '上传文件大小不超过50M'
}
},
methods: {
getFileList: function() {
this.fileList = this.$refs.fileUpload.fileList
console.log(this.fileList)
}
}
2、组件参数说明
分页组件由el-upload重新封装,理论上原有的属性按官方文档一样来使用,这里只列举自定义的一些属性或是对原属性的重定义。
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| countLimit | 上传文件数量 | number | — | 5 |
| sizeLimit | 文件大小限制 | number | — | 50M |
| tip | 提示信息 | string | — | |
| allowUpload | 允许上传 | boolean | true/false | true |
| allowDrag | 允许拖拽 | boolean | true/false | true |
| allowDowload | 允许下载 | boolean | true/false | true |
| initFileList | 初始文件列表 | array | — | [] |
| accept | 允许上传的文件类型 | string | — |
这些参数应用的场景有新增时文件上传、修改时文件回显、查看时文件下载(无下载权限时文件查看)
- 新增操作:allowUpload-true;allowDrag-true/false(自行选择);allowDowload-true
- 修改操作:allowUpload-true;allowDrag-true/false(自行选择);allowDowload-true;initFileList-[] 初始文件列表
- 查看操作:allowUpload-false;allowDowload-true/false(根据权限来设置是否可下载)
3、API接口服务
3.1、文件上传
- 请求方式:POST
- 接口地址:/file/upload
| 参数 | 参数名称 | 数据类型 |
|---|---|---|
| data | 文件binary | multipart/form-data |
- 应答格式:JSON
{
"code": 200,
"message": "调用成功!",
"data": {
"fileName": "4e7f3a15429bfda99bce42a18cdd1.jpeg",
"uploadId": "0a3153edd97040f29b6bbaeb6d734359"
}
}
返回的json数据中主要数据为uploadId上传id,后续的下载、删除等操作都是基于该id进行,该id可以存入自己的业务表,也可以业务数据保存后,将业务id调用接口更新文件列表中。
3.2、文件下载
- 请求方式:GET
- 接口地址:/file/{uploadId}
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 | 示例值 |
|---|---|---|---|---|---|
| uploadId | 上传id | String | 是 | 文件上传成功后返回的id | 0a3153edd970 |
| type | 文件打开方式 | String | 否 | 设置type值后在浏览器中打开文件,不支持的类型一样下载 | open |
- 应答格式:binary
通过浏览器直接下载,如果设置了type的值会以将header中的Content-Disposition设置为inline,支持的类型如图片、pdf直接在浏览器打开,不支持的类型一样采用下载。
3.3、文件删除
- 请求方式:DELETE
- 接口地址:/file/{uploadId}
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 | 示例值 |
|---|---|---|---|---|---|
| uploadId | 上传id | String | 是 | 文件上传成功后返回的id | 0a3153edd970 |
- 应答格式:json
{
"code": 200,
"message": "调用成功!",
"data": null
}
删除后没有具体的data,值为null,如需要前端判断,只要状态码code值为200表示删除成功。
3.3、更新业务ID
- 请求方式:PUT
- 接口地址:/file/{businessId}
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 | 示例值 |
|---|---|---|---|---|---|
| businessId | 业务id | String | 是 | 业务保存后返回的id | 0a3153edd970 |
| uploadIds | 上传id数组 | String[] | 是 | 文件上传列表中的id数组 |
- 应答格式:json
{
"code": 200,
"message": "调用成功!",
"data": null
}
更新后没有具体的data,值为null,如需要前端判断,只要状态码code值为200表示删除成功。
对于业务ID的更新,可以在自身service中一并更新了,还可以通过@Transactional保持同一个事务,调用filesService.updateBatchById(dataList)
// 更新业务id代码片断
@Autowired
private ISysFileService filesService;
filesService.updateBatchById(dataList)
3.4、获取业务ID对应的文件列表
- 请求方式:GET
- 接口地址:/file/{businessId}/list
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 | 示例值 |
|---|---|---|---|---|---|
| businessId | 业务id | String | 是 | 业务保存后返回的id | 0a3153edd970 |
- 应答格式:json
{
"code": 200,
"message": "调用成功!",
"data": [
{
"uploadId": "080d8d1aa99744dfad075ea91debcd39",
"id": "8_FRsF2hbPHTIHQXqupoKg",
"name": "项目简码-项目名称-立项汇报.pptx",
"size": 1085011,
"contentType": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"businessId": "75dd715937614cb58",
"createBy": "admin",
"createTime": "2020-06-12 17:18:27"
},
{
"uploadId": "153f21a8423f47fe8fcfcb9d2552c174",
"id": "VIXyonuIIquTEkLdd7CBPQ",
"name": "test.jpg",
"size": 411586,
"contentType": "image/jpeg",
"businessId": "75dd715937614cb58",
"createBy": "admin",
"createTime": "2020-06-12 08:47:19"
}
]
}
返回的 文件列表可以根据组件所需要的initFileList数据格式进行封装,回显到上传组件。
3.5、获取缩略图服务
- 请求方式:GET
- 接口地址:/file/{uploadId}/imgPreview
| 参数 | 参数名称 | 数据类型 | 是否必填 | 描述 | 示例值 |
|---|---|---|---|---|---|
| uploadId | 上传id | String | 是 | 图片上传后返回的id | 0a3153edd970 |
| width | 图片宽 | Integer | 否 | 单位为像素 | 128 |
| height | 图片高 | Integer | 否 | 单位为像素 | 128 |
| scale | 缩放比例 | Double | 否 | 小于1的值 | 0.5 |
scale、width,height为两种组合参数,都设置值优化scale,width,height必须同时设置值才有效,如果要显示原始图片大小,只传uploadId路径参数就可以了。
scale: 0.5 表示原始图片缩小50%
width/height: 128/128 表示生成的图片大小为宽:128像素;高:128像素
- 应答格式:binary
通过浏览器直接显示缩放的图片。
4、示例访问
- 示例文件上传路径:
src/views/demo/FileUpload.vue - 示例文件上传路径:
src/views/demo/ImageUpload.vue - 本地文件上传访问地址: http://localhost:8080/#/demo/file
- 本地图片上传访问地址: http://localhost:8080/#/demo/img
- 文件上传预览效果

- 图标修改:对于添加了其他文件格式,默认的图标不支持的情况下,可以自行添加svg图标,然后给配置进来即可
# svg 存放目录
src/icons/svg
# 组件格式映射
src/components/svg/SvgIcon.vue
# 定义文件类型映射的svg图标,如下:
const docMap = new Map()
docMap.set('application/x-zip-compressed', 'zip')
# 注意 application/x-zip-compressed 为文件类型,zip为svg图标名
- 图片上传预览效果(图片上传只提供demo,不提供组件,因实际项目需要展现的方式不一样,基于elementui中的展现方式自行开发,上传的方式与文件上传,图片多了一个预览,缩略图的功能,参见 3.5、获取缩略图服务 )

5、大文件上传
在项目中某些需求可能要上传上百M或好几个G的文件,对于传统的方式去上传会出现下面几种情况:
- 等待时间过长(前端不友好,以为系统功能出问题)
- 后面服务可能出现OOM
基于这些问题,在原有的文件上传接口服务中,扩展出针对大文件进行上传,主要实现:
- 文件分片上传(如前端拆分成10M一个文件提交)
- 文件分片并发上传(同时提交多个分片)
- 文件分片分布式上传(可以在前端并发分片时,后面给分发到不同的节点进行上传)
- 文件秒传(基于文件MD5值来验证是否已经上传了,如果存在直接返回文件上传成功)
5.1、 后端服务
waf-parent:2.1.0版本提供,后端采用基于aws s3提供的api,对于只要是兼容s3规范的对象存储,此功能都支持如:ceph、minio、OSS等
分片上传主要分为三个步骤:
- 初始化分片(生成上传ID )
- 分片上传(上传完后返回ETag标记,记录了当前分片号、eTag标记)
- 分片合并(将上传的分片返回的eTag列表进行文件合并)
根据前端组件对文件md5值提取,这里还添加了一个验证文件是否存在,用于文件秒传(取决于前端文件md5值的计算)
com.wiseda.waf.system.admin.controller.S3FilesController 接口示例如下:
@GetMapping("/chuckUpload")
public UploadResult checkUpload(Upload upload) {
// 检查文件是否存在
...
}
@PostMapping("/chuckUpload")
public UploadResult upload(Upload upload,MultipartFile file) throws Exception {
// 分片上传
...
}
@PostMapping("/mergeUpload")
public SysFile merge(@RequestBody UploadResult result){
// 合并上传分片
...
}
5.2、前端示例
在src/views/demo/ChuckUpload.vue中提供一个简单上传的demo,项目实际页面可以基于这个来修改
基本逻辑示例:
export default {
data() {
return {
options: {
// 设置option,上传的URL,分片数,秒传检测等
}
},
methods: {
onFileAdded(file) {
// 添加文件时,计算文件md5值
this.computeMD5(file)
},
computeMD5(file) {
......
},
onFileSuccess(rootFile, file, response, chunk) {
// 分片上传完成后,发起文件合并
......
}
}
}
