一、上传
1.1 前端示例
<template>
<div class="my-upload">
<el-upload
style="height: 100%"
ref="upload"
action="action"
:limit="limitNum"
:auto-upload="true"
:drag="true"
:accept="accept"
:show-file-list="false"
:list-type="listType"
:http-request="httpRequest"
:before-upload="beforeUpload"
:on-change="fileChange"
:on-exceed="exceedFile"
:on-success="handleSuccess"
:on-progress="handleProgress"
:on-error="handleError"
:on-remove="removeFile"
:file-list="fileList"
:class="status == 3? 'upload-red-border':'upload-border'"
>
<!--文件显示 #BBC1D9-->
<div style="width:100%">
<div class="upload-content">
<i :class="icon" :style="{'color':color}"></i>
<el-tooltip
class="item"
effect="dark"
:content="notice"
placement="top"
>
<span v-if="status === 1" :style="{'color':color}">{{text}}</span>
</el-tooltip>
<span v-if="status !== 1" :style="{'color':color}">
<div class= "box" v-if="status == 4">
<span class= "clip" :style= "clipStyle"></span>
<span class="clip-num">{{Math.round(progress)+"%"}}</span>
</div>
{{text}}
</span>
</div>
<!--点击上传 1-->
<div class="el-upload__text" v-if="status == 1">
您也可以将文件拖动到这里
<el-tooltip
class="item"
effect="dark"
:content="tip"
placement="top"
>
<i class="el-icon-warning"></i>
</el-tooltip>
</div>
<!--上传成功 2-->
<div class="el-upload__text" v-else-if="status == 2" style="display:flex">
<div style="width: 70%" class="file-name"><div class="ellipsis"><i class="el-icon-document"></i>{{fileName}}</div></div>
<div style="flex: 0 0 auto" class="del"><el-link type="danger" @click.stop="handleDelFile(file)">删除</el-link></div>
</div>
<!--上传中 4-->
<div class="el-upload__text" v-else-if="status == 4" style="display:flex">
<div style="width: 70%" class="file-name"><div class="ellipsis"><i class="el-icon-document"></i>{{fileName}}</div></div>
<div style="flex: 0 0 auto" class="del"><el-link type="primary" @click.stop="handleDelFile(file)">取消</el-link></div>
</div>
<!--上传失败 3-->
<div class="el-upload__text" v-else-if="status == 3" style="display:flex">
<div style="width: 70%" class="file-name"><div class="ellipsis"><i class="el-icon-document"></i>{{fileName}}</div></div>
<div style="flex: 0 0 auto" class="del"><el-link type="primary" @click.stop="handleDelFile(file)">重新上传</el-link></div>
</div>
</div>
</el-upload>
<div class="errTipText" v-show="status == 3"><i class="el-icon-warning-outline"></i>{{msg}} <div v-if="link != ''">您可以<div class="downModel" @click="downloadError">下载文件</div>查看原因</div>
</div>
</div>
</template>
<script>
export default {
name: "my-upload",
data () {
return {
clipStyle: {
transform: 'rotate(' + 3.6 * 0 + 'deg)'
},
limitNum: 2,
listType: '',
isPictureImg: false,
fileList: [],
menu: false,
progress: '0',
status: 1,
icon: 'el-icon-upload',
color: '#1E78FF',
text: '点击上传',
button: '',
msg: '',
formLabelWidth: '80px',
file: null,
fileName: '',
link: '',
};
},
props:{
action: {
type: String,
default: '#'
},
maxSize: {
type: Number,
default: 10
},
drag: {
type: Boolean,
default: true
},
accept: {
type: String
},
notice: {
type: String,
default: '请上传符合模板格式的文件哦!'
},
tip: {
type: String
},
template: {
type: Object,
default: () => {
return {}
}
},
module: {
type: String,
default: ''
},
errorUrl:{
type: String
}
},
methods: {
download(res) {
const content = res.data
const blob = new Blob([content], { type: 'application/vnd.ms-excel' })
const fileName = '错误文件.xlsx'
// this.exportExcelFile(blob, fileName)
if ('download' in document.createElement('a')) { // 非IE下载
var link = document.createElement('a')
link.download = fileName
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
document.body.appendChild(link)
link.click()
URL.revokeObjectURL(link.href)
document.body.removeChild(link)
} else {
// IE10+下载
navigator.msSaveBlob(blob, fileName)
}
},
downloadError(){
window.open(this.link)
},
httpRequest(param){
var fd = new FormData()
fd.append('file', param.file)
fd.append('name', param.file.name)
fd.append('template',JSON.stringify(this.template))
fd.append('module', this.module)
this.$axios({
url: this.action,
method: 'post',
data: fd,
headers: { 'Content-Type': 'multipart/form-data', 'Authorization': sessionStorage.getItem("token") },
onUploadProgress: progressEvent => {
// progressEvent.loaded:已上传文件大小
// progressEvent.total:被上传文件的总大小
param.file.percent = (progressEvent.loaded / progressEvent.total * 100)
param.onProgress(param.file)
}
}).then(res => {
if (res.data.success) {
param.onSuccess(res)
} else {
param.onError(res)
}
}).catch(error => {
param.onError(error)
console.log(error)
})
},
handleProgress(event, file, fileList){
if(file){
this.status = 4
this.text = '上传中'
this.icon = ''
this.fileName = file.name
this.color = '#BBC1D9'
this.button = '取消'
this.progress = event.percent
}else{
this.$refs.upload.abort(file)
this.status = 3
this.progress = 0
}
},
removeFile(file, fileList){
if(fileList.length > 0){
this.file = fileList[fileList.length-1]
}else{
this.file = null
}
},
handleDelFile(file){
this.text = '点击上传'
this.icon = 'el-icon-upload',
this.color = '#409eff',
this.msg = ''
this.link = ''
this.fileName = ''
this.status = 1
this.$refs.upload.handleRemove(file);
this.$emit("handleDisable",true)
},
// 文件超出个数限制时的钩子
exceedFile(file, fileList) {
// this.$refs.upload.abort(file)
},
// 文件状态改变时的钩子
fileChange(file, fileList) {
if (fileList.length > 1) {
fileList.splice(0, 1)
this.fileName = ''
}
if(fileList.length > 0){
this.file = fileList[fileList.length-1]
this.fileName = file.name
}else{
this.showFileList = false
}
},
// 上传文件之前的钩子, 参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传
beforeUpload(file) {
this.msg = '';
var extension = file.name.substring(file.name.lastIndexOf('.') + 1)
if (this.accept != '' && this.accept.indexOf(extension)<0) {
this.fileName = file.name
this.msg = '文件格式错误'
this.status = 3
return false
}
var size = file.size / 1024 / 1024
// var imgList = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
// if(imgList.indexOf(extension) > 0){
// if(size > 5) {
// this.fileName = file.name
// this.msg = '图片大小超过限制'
// this.status = 3;
// this.button = '重新上传'
// this.text = '上传失败'
// this.color = '#F43C3C'
// this.icon = 'el-icon-error'
// this.$emit("handleDisable",true)
// return false;
// }
// }else{
if (size > this.maxSize) {
this.fileName = file.name
this.msg = '文件大小超过限制'
this.status = 3;
this.button = '重新上传'
this.text = '上传失败'
this.color = '#F43C3C'
this.icon = 'el-icon-error'
this.$emit("handleDisable",true)
return false;
}
// }
},
// 文件上传成功时的钩子
handleSuccess(res, file, fileList) {
if(res.data.msg != '操作成功'){
this.status = 3;
this.fileName = file.name
this.icon = 'el-icon-error'
this.button = '重新上传'
this.text = '上传失败'
this.color = '#F43C3C'
this.msg = res.data.msg
if(res.data.data != ''){
this.link = res.data.data
}
if(!res.data.msg){
this.msg = '上传失败,请再试一次'
}
}else{
this.status = 2;
this.icon = 'el-icon-success'
this.text = '上传成功'
this.button = '删除'
this.color = '#67C23A'
}
// res.data.data.size = file.size
this.$emit("handle",res)
},
// 文件上传失败时的钩子
handleError(err, file, fileList) {
this.status = 3;
this.fileName = file.name
this.icon = 'el-icon-error'
this.button = '重新上传'
this.text = '上传失败'
this.color = '#F43C3C'
if(err.data && err.data.msg){
this.msg = err.data.msg
}else {
this.msg = '上传失败,请再试一次'
}
if(err.msg || err.message){
this.msg = err.msg || err.message
}
if(err.response){
this.msg = err.response.data.msg
}
if(err.data && err.data.code == 1601){
this.link = err.data.data.link
}
this.$emit("handleDisable",true)
},
clearFileData(){
this.text = '点击上传'
this.icon = 'el-icon-upload',
this.color = '#1E78FF',
this.msg = ''
this.fileName = ''
this.status = 1
this.fileList = []
this.file = null
}
}
};
</script>
<style lang="scss">
.my-upload {
width: 250px;
height: 110px;
.ellipsis{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.el-upload-dragger .el-upload__text{
line-height: 18px;
}
.upload-content {
font-size: 14px;
line-height: 18px;
color: #409eff;
margin-top: 28px !important;
margin-bottom: 16px !important;
cursor: pointer;
}
.upload-content i {
font-size: 22px;
line-height: 24px;
color: #409eff;
}
.upload-content span {
vertical-align: text-top;
}
.el-upload-dragger {
display: flex;
border-radius: 8px;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-box-align: center;
flex-direction: column;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
width: 248px !important;
height: 110px !important;
border:none !important;
background:transparent !important;
}
.uploadFile {
margin: 0 auto;
margin-top: 32px;
width: 250px;
}
.downModel {
font-size: 14px;
line-height: 22px;
color: #409eff;
margin-bottom: 12px;
cursor: pointer;
display:inline-block;
}
.upload-content {
font-size: 14px;
line-height: 18px;
color: #409eff;
margin-top: 28px !important;
margin-bottom: 16px !important;
cursor: pointer;
}
.el-icon-upload {
margin: 0;
}
.upload-content i {
color: #409eff;
margin: 0;
line-height: 20px;
font-size: 20px;
}
.upload-content span {
vertical-align: text-top;
}
.upload-border{
background: #F9F9FC;
border: 1px dashed #C3C7CE;
border-radius: 8px;
}
.upload-border:hover {
background: #F9F9FC;
border: 1px dashed #504EF2;
border-radius: 8px;
}
.upload-red-border {
background: #F9F9FC;
border: 1px dashed #F43C3C;
border-radius: 8px;
}
.clip{
box-sizing: border-box;
border-top: 2px solid #1E78FF;
border-left: 2px solid #1E78FF;
border-right: 2px solid #ccc;
border-bottom: 2px solid #ccc;
border-radius: 50%;
vertical-align: text-top;
transform: rotate(
0deg
);
width: 16px;
height: 16px;
display: inline-block;
margin-right: 6px;
}
.box{position: relative;
/*width: 14px;*/
height: 14px;
overflow: hidden;
width: auto;
text-align: center;
display: inline-table;
color: #1E78FF;
}
.box span {
vertical-align: middle;
}
.el-progress {
align-items: center;
display: flex;
width: 100%;
}
.clip-num {
width: auto;
padding: 0 2px;
display: inline-block;
background: transparent;
}
.errTipText {
color: #F43C3C;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 22px;
}
/deep/ .el-upload-dragger {
width: 248px !important;
height: 110px !important;
border:none !important;
background:transparent !important;
}
/deep/ .el-icon-upload {
margin: 0;
}
}
</style>
1.2 前端调用
<knowledge-upload ref="knowledgeUpload" @handle="handleUpload" @handleDisable="handleDisable" :show-file-list="false" :module="upload.module" :action="upload.action" :notice="upload.notice" :accept="upload.accept" :list-type="upload.listType" :tip="upload.tip" :template="template" :drag="true"></knowledge-upload>
upload: {
importDialogVisible: false,
fileList: [],
tip: '仅支持上传xls或者xlsx文件 大小不超过10m',
listType: '',
action: '/integration/word/upload',
accept: '.xlsx,.xls',
notice: '点我上传',
module: 'word',
},
1.3 后端示例
@PostMapping(value = "/upload")
@ApiOperation(value = "导入")
public R<Boolean> upload(@Validated UploadDTO uploadDTO) {
String template = uploadDTO.getTemplate();
String tmpDir = System.getProperty("java.io.tmpdir") + "upload/";
File tmpDirFile = new File(tmpDir);
if (!tmpDirFile.exists() && !tmpDirFile.isDirectory()) {
tmpDirFile.mkdir();
}
String pathName = tmpDir + System.currentTimeMillis();
File file = new File(pathName);
try {
uploadDTO.getFile().transferTo(file);
service.upload(template, file, pathName);
} catch (Exception e) {
e.printStackTrace();
}
return R.status(true);
}
@Data
public class UploadDTO {
@NotNull(message = "文件不能为空")
private MultipartFile file;
@NotBlank(message = "模板不能为空")
private String template;
}
二、下载
2.1 前端示例
<el-button icon="el-icon-download" size="small" type="primary" @click="download">导出</el-button>
download(){
let fd = new FormData();
fd.append("template", JSON.stringify(this.template));//模板
download(fd).then(res => {
this.$message({
showClose: true,
message: "下载成功",
type: "success"
});
this.download(res);
})
},
download(res){
const content = res.data;
const blob = new Blob([content]);
const fileName = "导出.xlsx";
if ('download' in document.createElement('a')) { // 非IE下载
var link = document.createElement('a');
link.download = fileName;
link.style.display = 'none';
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href); // 释放URL 对象
document.body.removeChild(link);
} else { // IE10+下载
navigator.msSaveBlob(blob, fileName);
}
},
2.2 后端代码示例
@PostMapping(value = "/download")
@ApiOperation(value = "导出")
public ResponseEntity<byte[]> download(@Validated DownloadDTO downloadDTO) {
String displayName = System.currentTimeMillis()+".xlsx";
byte[] bytes = service.download(downloadDTO, displayName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", displayName);
return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
}