vue文件上传通用组件
<template>
<div class="upload-button">
<template v-if="multiple">
<input
ref="input"
type="file"
multiple="multiple"
:accept="acceptType"
@change="handleChange"
/>
</template>
<template v-else>
<input
ref="input"
type="file"
:accept="acceptType"
@change="handleChange"
/>
</template>
</div>
</template>
<script>
import { reactive, ref } from "@vue/composition-api";
import { Message } from "element-ui";
import { post } from "axios"; // 请求也是的,建议直接使用项目中已经封装好的请求函数来调接口。我这是自己搭建的练手的项目,就没去封装请求。
import commonApi from "@/api/common"; // 这个是接口地址,根据自己需求改。
const defaultType = [
"bmp",
"jpg",
"png",
"tif",
"gif",
"pcx",
"tga",
"exif",
"fpx",
"svg",
"psd",
"cdr",
"pcd",
"dxf",
"ufo",
"eps",
"ai",
"raw",
"WMF",
"webp",
];
export default {
props: {
multiple: {
// 是否多选
type: Boolean,
default: false,
},
acceptType: {
// 文件类型
type: String,
default: "image/*",
},
type: {
// 限制上传文件类型
type: String,
default: undefined,
},
size: {
// 限制上传文件尺寸
type: String,
default: undefined,
},
bulk: {
// 限制上传文件大小
type: Number,
default: 0,
},
},
setup(props, c) {
const { bulk, type, size, multiple } = reactive(props);
const uploading = ref(false);
const input = ref(null);
const url = ref(undefined);
let uploadFiles = reactive([]);
const inputClick = () => {
if (uploading.value) {
return Message.warning("请等待前面的文件完成上传!");
}
return input.value.click();
};
const handleChange = ({ target }) => {
if (multiple) uploadFiles = [...target.files];
uploadFile(target.files[0]);
target.value = "";
};
const uploadFile = async (file) => {
try {
// 限制文件类型
if (type) await detectorType(file);
//
if (bulk) await detectorBulk(file);
if (size) await detectorSize(file);
uploading.value = true;
const fd = new FormData();
url.value = commonApi.addUserEmoticon;
fd.append("file", file); // 可以通过这种形式,来传递其他项目中要传递的参数。
const data = await post(url.value, fd, {
headers: {
"content-type": "multipart/form-data",
},
});
c.emit("url", data); // 将请求到的数据 抛出去
uploaded(false);
} catch (err) {
uploaded(err);
}
};
const detectorType = (file) => {
return new Promise((resolve, reject) => {
const sizeList = type.split(",");
const fileSize = file.name.split(".");
const fileExtension = fileSize[fileSize.length - 1].toLowerCase();
if (!sizeList.includes(fileExtension)) {
if (!defaultType.includes(fileExtension)) {
Message.error("文件类型不对!");
} else {
Message.error("图片类型不对!");
}
reject(new Error());
} else {
resolve(true);
}
});
};
const detectorBulk = (file) => {
return new Promise((resolve, reject) => {
const fileSize = file.size / 1024 / 1024;
if (fileSize > bulk) {
Message.error(`大小超出${bulk}M`);
reject(new Error());
} else {
resolve(true);
}
});
};
const detectorSize = (file) => {
return new Promise((resolve, reject) => {
const image = new Image();
const URL = window.URL || window.webkitURL;
image.onload = () => {
const sizes = size.split(",");
if (
image.width === Number(sizes[0]) &&
image.height === Number(sizes[1])
) {
resolve(true);
} else {
Message.error({
type: "error",
message: `请上传尺寸为 ${sizes.join(" x ")} 的图片`,
});
reject(new Error());
}
};
image.src = URL.createObjectURL(file);
});
};
const uploaded = (err, state = false) => {
uploading.value = false;
if (!err) {
if (multiple && uploadFiles.length > 1) {
uploadFiles = uploadFiles.slice(1, uploadFiles.length - 1);
uploadFile(uploadFiles[0]);
} else {
Message.success("上传成功!");
}
}
};
return {
input,
inputClick,
handleChange,
};
},
};
</script>
<style scoped lang="less"></style>
上传组件图片预览
使用 fileReader()这个构造函数
reader.readAsDataURL(file)
const fr = new fileReader()
fr.onload = function(){
this.imgsrc = fr.result
}