从iview官网可以看到上传附件的几个属性。
官网:https://www.iviewui.com/components/upload
可以看到,iview提供了<upload>标签及一些属性,用于用户上传附件,upload自带action属性,会根据这个地址自动上传附件,功能挺好,但是我们做开发的,往往不会这么存储的,我们需要携带一些其他的参数,还有校验等操作,否则上传的东西又乱又多不可控。
通过查看官网的API我们看到iview提供了一个方法阻止默认上传:before-upload
这个方法是在上传文件之前做的一些操作,当这个方法返回false表示手动上传,不会通过action属性来提交文件。
iview官网的upload相关的API:
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
action | 上传的地址,必填 | String | - |
headers | 设置上传的请求头部 | Object | {} |
multiple | 是否支持多选文件 | Boolean | false |
paste | 是否支持粘贴上传文件 | Boolean | false |
disabled 3.3.0 | 是否禁用 | Boolean | false |
data | 上传时附带的额外参数 | Object | - |
name | 上传的文件字段名 | String | file |
with-credentials | 支持发送 cookie 凭证信息 | Boolean | false |
show-upload-list | 是否显示已上传文件列表 | Boolean | true |
type | 上传控件的类型,可选值为 select (点击选择),drag (支持拖拽) | String | select |
accept | 接受上传的文件类型 | String | - |
format | 支持的文件类型,与 accept 不同的是,format 是识别文件的后缀名,accept 为 input 标签原生的 accept 属性,会在选择文件时过滤,可以两者结合使用 | Array | [] |
max-size | 文件大小限制,单位 kb | Number | - |
before-upload | 上传文件之前的钩子,参数为上传的文件,若返回 false 或者 Promise 则停止上传 | Function | - |
on-progress | 文件上传时的钩子,返回字段为 event, file, fileList | Function | - |
on-success | 文件上传成功时的钩子,返回字段为 response, file, fileList | Function | - |
on-error | 文件上传失败时的钩子,返回字段为 error, file, fileList | Function | - |
on-preview | 点击已上传的文件链接时的钩子,返回字段为 file, 可以通过 file.response 拿到服务端返回数据 | Function | - |
on-remove | 文件列表移除文件时的钩子,返回字段为 file, fileList | Function | - |
on-format-error | 文件格式验证失败时的钩子,返回字段为 file, fileList | Function | - |
on-exceeded-size | 文件超出指定大小限制时的钩子,返回字段为 file, fileList | Function | - |
default-file-list | 默认已上传的文件列表,例如: | Array | [] |
在了解了这些api后,我们就可以写自己的代码了。
html:
<!DOCTYPE html>
<#import "/spring.ftl" as s />
<#assign security=JspTaglibs["http://www.springframework.org/security/tags"] />
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<#include "/inc/head.html">
<style scoped>
.demo-upload-list {
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
margin-right: 4px;
}
.demo-upload-list img {
width: 100%;
height: 100%;
}
.demo-upload-list-cover {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .6);
}
.demo-upload-list:hover .demo-upload-list-cover {
display: block;
}
.demo-upload-list-cover i {
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}
.ivu-icon {
line-height: 58px;
}
</style>
</head>
<body style="height:100%;background: #ffffff;">
<div id="app" v-cloak>
<Layout style="height:100%">
<i-Header ref="queryHeader" data-querypanel="hide">
<row>
<i-form @submit.native.prevent :model="queryForm" ref="queryForm" inline :label-width="90">
<i-Col span="5">
<Form-Item label="批次" style="width:100%;">
<!--查询条件-->
</Form-Item>
</i-Col>
</i-form>
</row>
</i-Header>
<i-Content>
<Layout>
<i-Header data-actionpanel :style="{height:ActionHeight+'px'}">
<i-Col :xxl="16" :xl="16" :lg="16" :md="16">
<form-item :label-width="10">
<i-button type="info" @click="uploadXszpButton">导入考生照片</i-button>
</form-item>
</i-Col>
</i-Header>
</Layout>
</i-Content>
</Layout>
<!--批量上传图片-->
<Modal width="600" v-model="modelUploadXszp" title="导入学生照片" :mask-closable="false">
<i-Form :label-width="80">
<Row>
<Form-Item label="友情提示:">
<p>1.支持多个文件同时上传</p>
<p>2.上传格式只识别<span style="color:green;"> jpg, jpeg, png</span></p>
<p>3.<span style="color:darkred;">每张图片最好不要超过200kb,最大不超过500kb</span>,否则页面展示会有卡顿现象产生</p>
<p>4.选择图片的时候可以划选,可以拖拽,也可以按住键盘的“Ctrl”键后点击想要上传的图片</p>
</Form-Item>
<div>
<Upload ref="upload"
multiple
:before-upload="handleBeforeUpload"
action="">
<i-Button icon="ios-cloud-upload-outline">选择图片</i-Button>
</Upload>
</div>
</Row>
</i-Form>
<div slot="footer">
<i-Button type="text" @click="modelUploadXszp=false">取消</i-Button>
<i-Button type="success" @click="uploadXszpSave">导入照片</i-Button>
</div>
</Modal>
</div>
</body>
<script src="<@s.url '/***/***.js'/>"></script>
<#include "/inc/footer.html">
</html>
js:
var app = new Vue({
el: '#app',
mixins: [layoutHeight],
data: {
dataa: [],
modelUploadXszp: false,
kshModal: false,
//图片
defaultList: [ ],
uploadList: []
},
methods: {
/** 批量上传头像===start=== */
uploadXszpButton: function () {
var self = this;
self.modelUploadXszp = true;
},
handleRemove (file) { 从 upload 实例删除数据
var self = this;
const fileList = self.$refs.upload.fileList;
self.$refs.upload.fileList.splice(fileList.indexOf(file), 1);
},
handleBeforeUpload (file) {
var self = this;
//先校验个数,再校验文件类型,再校验文件大小
if(this.uploadList.length<2) {
if (!/image\/\w+/.test(file.type)) {
self.$Notice.warning({
title: '文件格式不正确',
desc: '文件 ' + file.name + ' 格式不正确,请上传 jpg、png、jpeg 三种格式内的图片。'
});
self.file = null;
}else if (file.size > 512*1024) {
alert(file.size);
self.$Message.error(file.name + '大小超过 512 kb!');
self.file = null;
}else{
self.uploadList.push(file);
}
}else{
self.$Notice.warning({
title: '一次最多只能上传2个[jpg、jpeg、png]的图片文件'
});
}
return false;/**当你直接false的时候, 就阻止了iview的upload的一切其他的功能了,整个的校验就停止了,
包括校验文件的大小、个数、类型,当然也包括action的自动执行,所以不需要写其他的函数了,
所有的验证你就都写到这个前置钩子里吧。这里阻止upload自定义的这些事件,主要是为了让其走
我写的push功能了,否则不太受控制,不友好。*/
// return true; 如果这里返回true的话,那么upload会根据action的地址直接提交到后台,并自动进行其他的事件,如检查大小、类型、个数什么的。
},
uploadXszpSave:function(){
var self = this;
var formData = new FormData();
for (var i = 0; i < self.uploadList.length; i++) {
formData.append("files", self.uploadList[i]); // 文件对象
}
if (self.uploadList.length > 0) {
self.spinShow=true;
$.ajax({
url: baseUrl + 'kshwh/uploads',
dataType: 'json',
type: 'POST',
async: false,
data: formData,
cache: false, //上传文件无需缓存
processData: false, // 使数据不做处理
contentType: false, // 不要设置Content-Type请求头
success: function (res) {
if (res.code == '200') {
self.spinShow=false;
self.uploadList = [];
self.$Message.success({
background: true,
duration: 5,
content: "头像导入成功"
});
self.modelUploadXszp = false;
setTimeout(function () {
self.query();
},5000);
}else{
self.$Message.error({
background: true,
duration: 10,
content: "头像导入失败"
});
self.spinShow=false;
return ;
}
},
error:function(e){
self.$Message.error({
background: true,
duration: 10,
content: "头像导入失败"
});
self.spinShow=false;
return ;
}
}
);
} else {
self.$Message.error("请至少上传一个文件");
}
}
/** 批量上传头像===end=== */
},
created: function () {
var self = this;
},
computed: {},
mounted: function () {
var self = this;
this.uploadList = this.$refs.upload.fileList;
}
});
java:
实体类:private String zp; 没有使用 byte[] 类型,太麻烦,后期维护会给别人带来麻烦
controller:
/**
* 通过考生号或者身份证号更新学生的头像
* FileManager 返回值 包含属性
* savename 文件在FTP上的物理路径存入数据库供下载使用需拼一下ftp.baseUrl
* filename 实际文件名 显示使用
* type 文件拓展名
* size 文件大小 千字节
*/
@RequestMapping("/uploads")
public ReturnT uploads(@RequestParam("files") MultipartFile files[]) throws Exception {
MultipartFile[] fileArr = files;
int len = files.length;
String fileName = "";//上传的文件名字
String ksh_sfzh = "";//文件名截取后的字符串,是考生号或者身份证号
String zp_base64;//上传的照片转换成base64格式的数据存入数据库
XszzbmEntity tyent = new XszzbmEntity();
try {
for(int xx = 0; xx < len; ++xx) {
tyent = new XszzbmEntity();
MultipartFile file = fileArr[xx];
fileName = file.getOriginalFilename();
ksh_sfzh = fileName.substring(0,fileName.lastIndexOf("."));
BASE64Encoder encoder=new BASE64Encoder();
zp_base64 = "data:image/jpg;base64,"+encoder.encode(file.getBytes());
tyent.setSfzh(ksh_sfzh);
tyent.setZpstr(zp_base64);
bkshService.updateZpByKshOrSfzh(tyent);//通过考生号或者身份证号更新学生的头像
}
} catch (Exception e) {
e.printStackTrace();
return ReturnT.FAIL;
}
return ReturnT.SUCCESS;
}
数据库:
zp: clob