<template>
<el-upload
ref="single-upload"
:action="uploadConf.action"
:multiple="false"
:headers="uploadConf.headers"
:data="uploadConf.data"
:before-upload="onBeforeUpload"
:on-progress="onProgress"
:on-success="onSuccess"
:show-file-list="false"
>
<slot></slot>
</el-upload>
</template>
<script>
import getUploadSign from "@/api";
import generateId from 'nanoid/generate';
// 随机文件名
export default {
name: "CSingleUpload",
components: {},
props: {
accept: {
type: Array,
default: () => []
},
maxFileSize: {
type: Number,
default: 20
},
files: {
type: Array,
default: () => []
}
},
data() {
return {
fileList: [],
uploadConf: {
action: "",
headers: {},
data: {},
fileList: []
},
fileObj: null,
};
},
methods: {
// 上传前拦截
async onBeforeUpload(file) {
const { size, type, name, uid } = file;
const oldName = name;
const nameArr = oldName.split('.');
const fileName = nameArr[0] + '-' + generateId('0123456789qwertyuiopasdfghjklzxcvbnm', 15) + '.' + nameArr[1];
// 判断文件类型
// const isFileType = this.accept.some(accept => accept === type);
// if (!isFileType) {
// this.$message.warning(`该文件(${oldName})类型(${type})不支持`);
// return Promise.reject();
// }
// 判断文件大小
const KB = size / 1024;
const MB = KB / 1000;
if (MB > this.maxFileSize) {
let unit = `${this.maxFileSize}m`;
if (this.maxFileSize < 1) {
unit = `${Math.floor(this.maxFileSize * 1000)}kb`;
}
this.$message.warning(`该文件(${oldName})大小已超过限制(${unit})`);
return Promise.reject();
}
// 请求签名
const sign = await getUploadSign({ dir: type.split('/')[0], key: fileName });
// 显示上传对象
this.fileObj = {
type,
size,
uid,
oldName,
name: fileName,
url: (window.URL || window.webkitURL).createObjectURL(file),
ossUrl: `${sign.host}/${sign.dir}${fileName}`,
progress: 0,
isUpload: false
};
// 填充签名参数
this.uploadConf.data = {
key: `${sign.dir}${fileName}`,
policy: sign.policy,
OSSAccessKeyId: sign.accessid,
success_action_status: 200,
signature: sign.signature,
callback: sign.callback,
};
this.uploadConf.action = sign.host;
this.uploadConf.headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST"
};
// return Promise.reject();
},
// 更新文件上传进度
onProgress(event) {
const { percent } = event;
this.$emit("on-progress", percent);
},
// 更新文件上传成功状态
onSuccess(response, file) {
this.$emit('successCBK', this.fileObj.ossUrl, this.fileObj);
},
}
};
</script>
<style lang="less" scoped>
</style>
这种下载文件的方式兼容性比较好,一般不会出现跨域问题,如果使用的是axios封装的方法下载可能跨域。
export function downloadFile2(url, filename) {
/**
* 下载文件
* 原理:通过获取文件内容转译为二进制,传给创建a标签下载
* @param url 文件地址url
* @param filename 下载保存的名字
*/
var downloadFileBya = function (fileName, content) {
var aLink = document.createElement('a');
var blob = new Blob([content]);
var evt = document.createEvent("MouseEvents");
evt.initEvent("click", true, true);
if (fileName) {
aLink.download = fileName;
}
aLink.target = "_blank";
aLink.href = URL.createObjectURL(blob);
aLink.dispatchEvent(evt);
}
// 拿文件的名字
var fileNameFromHeader = function (disposition) {
if (disposition) {
let index = disposition.lastIndexOf("\/");
return decodeURIComponent(disposition.substring(index + 1, disposition.length));
}
return "undefine_file";
}
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.responseType = "blob";
xhr.open('GET', url, true);
xhr.onload = function () {
if (this.status == 200) {
// var blob = this.response;
var donwloadName = filename != undefined ? filename : fileNameFromHeader(xhr.responseURL);
downloadFileBya(donwloadName, xhr.response);
} else {
console.error("请求下载文件错误,请求错误码:" + this.status);
return false;
}
}
xhr.send();
}