文件上传组件
<template>
<van-uploader v-model="fileListed" multiple :after-read="afterRead" :max-count="maxCount" :before-read="beforeRead" @delete="deleteUpload" />
</template>
<script>
import { defineComponent, reactive, toRefs, computed, ref } from 'vue';
import axios from 'axios';
import { Dialog, Notify } from 'vant';
import Compressor from 'compressorjs';
export default defineComponent({
name: 'uploader',
components: {
[Dialog.Component.name]: Dialog.Component,
[Notify.Component.name]: Notify.Component
},
props: {
fileList: {
type: Array,
default: []
},
maxCount: {
type: Number,
default: -1
},
maxSize: {
type: Number,
default: 5
}
},
emits: ['uploadSuccess', 'uploadDetele'],
setup(props, { emit }) {
const state = reactive({
excelUrl: import.meta.env.VITE_MODE_PATH + '你的文件上传api',
headers: {
token: JSON.parse(localStorage.getItem('token'))
}
});
const fileListed = ref([]);
computed(() => {
let arr = JSON.parse(JSON.stringify(props.fileList));
if (arr.length > 0) {
arr.map((item) => {
if (item.url.indexOf(window.$config.IMAGEURL) == -1) {
item.url = window.$config.IMAGEURL + item.url;
}
});
}
fileListed.value = arr;
return;
});
const afterRead = async (file) => {
let formData = new FormData();
if (file.file.size > 1024 * 300) {
let img = file.file;
if (!['jpeg', 'jpg'].includes(img.type)) {
img = await ConvertImage(img);
compressorImage(img, 'file', 0.9).then((f) => {
if (f.size >= props.maxSize * 1024 * 1024) {
$Toast(`文件大小不能超过${props.maxSize}M`);
} else {
formData.append('file', f);
uploadFile(formData);
}
});
}
} else {
formData.append('file', file.file);
uploadFile(formData);
}
};
const uploadFile = (formData) => {
const config = {
headers: {
'Content-Type': 'multipart/form-data',
token: state.token
}
};
axios.post(state.excelUrl, formData, config).then((res) => {
if (res.data.code == 1) {
Notify({
type: 'success',
message: '图片上传成功'
});
emit('uploadSuccess', res.data.data);
} else {
$Toast('文件服务异常,请联系管理员!');
}
});
};
const beforeRead = (file) => {
if (file.type == 'image/jpeg' || file.type == 'image/png') {
return true;
} else {
$Toast('请上传 jpeg/png 格式图片');
return false;
}
};
const deleteUpload = (file, detail) => {
Dialog.confirm({
title: '删除',
confirmButtonText: '确认',
cancelButtonText: '取消',
message: '是否确认删除此图片'
})
.then(() => {
emit('uploadDetele', detail.index);
Notify({ type: 'success', message: '删除成功' });
})
.catch((error) => {
Notify({
message: '已取消删除',
color: '#999999',
background: '#F5F5F5'
});
});
};
const compressorImage = (image, backType, quality) => {
return new Promise((resolve, reject) => {
new Compressor(image, {
quality: quality || 0.8,
success(result) {
let file = new File([result], image.name, { type: image.type });
if (!backType || backType == 'blob') {
resolve(result);
} else if (backType == 'file') {
resolve(file);
} else {
resolve(file);
}
},
error(err) {
console.log('图片压缩失败---->>>>>', err);
reject(err);
}
});
});
};
function ConvertImage(file) {
return new Promise((resolve, reject) => {
const fileName = file.name.substring(0, file.name.indexOf('.'));
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = function (e) {
let image = new Image();
image.src = e.target.result;
image.onload = function () {
let canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
imageWidth = image.width,
imageHeight = image.height,
data = '';
canvas.width = imageWidth;
canvas.height = imageHeight;
context.drawImage(image, 0, 0, imageWidth, imageHeight);
data = canvas.toDataURL('image/jpeg');
var newfile = dataURLtoFile(data, fileName + '.jpeg');
resolve(newfile);
};
};
});
}
function dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
}
return {
...toRefs(state),
afterRead,
beforeRead,
deleteUpload,
fileListed
};
}
});
</script>
<style scoped>
:deep(.van-image__img) {
object-fit: contain !important;
}
</style>
页面使用
<uploader :fileList="fileList" :maxCount="6" @uploadDetele="detaleApply" @uploadSuccess="uploadApply"></uploader>
const uploadApply = (res) => {
state.fileList.push({ url: res });
};
const detaleApply = (res) => {
state.fileList.splice(res, 1);
};