JS+Vue 自定义文件上传 + Vue Upload 封装
可直接使用的代码
function uploadIframe(callback) {
let input = document.createElement('input');
input.setAttribute('type', 'file');
// 设置为多选选中文件 | 单选情况下不要设置
// input.setAttribute("multiple", 'muttiple')
// 设置 accept 为 .png,.jpg 类型 | 表示为弹出框选择文件的时候只能选中 png 和 jpg后缀的文件
input.setAttribute('accept', '.png,.jpg');
input.onchange = function() {
var file = this.files[0];
callback(file)
};
// 执行 click 事件,弹出文件选择框
input.click();
}
function uploadImage(formData) {
// 上传逻辑
return "test.png";
}
function uploadFile({ file }) {
let formdata = new FormData();
formdata.append('file', file);
uploadImage(formdata)
.then(filename => {
})
.catch(err => {
console.log(err);
})
.finally(() => {
console.log("上传完成");
});
},
完整代码 Api
import request from '@/utils/request';
// 此为七牛云 获取 token + 直传逻辑
export function uploadImage(data, sign = '') {
return (async function upload() {
const signData = await getUplaodSign().then(response => {
const signData = response.data;
return signData;
});
const { uploadUrl, token, host, dir } = signData;
data.append('token', token);
const result = await request({
url: uploadUrl,
method: 'post',
data: data
}).then(({ hash, key, url }) => {
console.log(arguments);
return {
file: url
};
}).catch(r => {
console.log(r);
});
return result;
})();
}
组件
<template>
<div v-loading.fullscreen.lock="fullscreenLoading">
<!-- <input type="file" value="upload" :accept="accept" class="el-button el-button--file el-button--small" @change="uploadImage" /> -->
<el-upload v-if='!isMobile' style="max-width: 500px" :http-request="uploadFile" list-type="picture-card" :on-remove="onRemove" :on-preview="onPreview" class="upload-demo" :file-list="fileList" :accept="accept" :show-file-list="showFileList">
<i class="el-icon-plus"></i>
</el-upload>
<div v-else>
<el-image v-if='fileImage'
style='margin-right: 5px'
:src="fileImage"
:preview-src-list="[fileImage]">
</el-image>
<el-button type='primary' @click='fileUpload'>相册上传</el-button>
</div>
<el-dialog :visible.sync="dialogVisible" :append-to-body="true">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<el-drawer size='100%' :visible.sync="photoVisible" title='图片上传' :append-to-body="true">
<Camera v-if='photoVisible' @upload='uploadBase64'/>
</el-drawer>
</div>
</template>
<script>
import { uploadImage } from '@/api/tool';
import { Message } from 'element-ui';
/**
* base64转file
* base64格式:data:image/png;base64,iVBORw0KGgoAAAANSU...
* @param {*} dataURL base64编码数据
* @param {*} filename 文件名称
*/
function dataURLToFile(dataURL, filename){
const arr = dataURL.split(','),
mime = arr[0].match(/:(.*?);/)[1], //mime类型 image/png
bstr = atob(arr[1]); //base64 解码
let n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
//return new Blob([a8arr], {type: mime});
}
function uploadIframe(callback) {
let input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', '.png,.jpg');
input.onchange = function() {
var file = this.files[0];
callback(file)
};
// 执行 click 事件,弹出文件选择框
input.click();
}
export default {
props: {
validate: {
type: String,
default: () => {
return '';
}
},
sign: {
type: String,
default: () => {
return '';
}
},
index: {
type: String,
default: () => {
return '';
}
},
accept: {
type: String,
default: () => {
return '';
}
},
size: {
type: String | Number,
default: () => {
return '';
}
},
uploaded: {
type: String,
default: () => {
return '';
}
},
value: {
type: String,
default: () => {
return '';
}
}
},
data() {
return {
photoVisible: false,
loadingService: '',
fileList: [],
showFileList: true,
dialogImageUrl: '',
dialogVisible: false,
cameraPhoto: null,
fullscreenLoading: false
};
},
created() {
// 默认传了空数组
if (this.value && !Array.isArray(this.value)) {
this.fileList.push({
name: this.value,
url: this.value
});
} else {
this.fileList = [];
}
},
methods: {
loading() {
this.loadingService = this.$loading({
lock: true,
text: 'Uploading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
},
onPreview(file) {
// this.$confirm('Do you want to view your uploaded file?', 'Tips', {
// confirmButtonText: 'Yes',
// cancelButtonText: 'No',
// type: 'warning'
// })
// .then(() => {
// window.open(file.url);
// })
// .catch(() => {});
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
uploadFile({ file }) {
let formdata = new FormData();
if (this.size) {
if (file.size > this.size * 1000000) {
Message.error(this.validate);
return false;
}
}
formdata.append('file', file);
this.loading();
this.showFileList = false;
uploadImage(formdata, this.sign)
.then(data => {
this.fileList = [{ name: data.file, url: data.file }];
this.$emit('uploadSuccess', {
file: data.file,
key: this.index
});
Message.success('Upload succeeded');
this.showFileList = true;
})
.catch(err => {
this.$emit('uploadError', err);
})
.finally(() => {
this.loadingService.close();
});
return false;
},
onRemove() {
this.$emit('onRemove');
},
photoUploadDialog() {
this.photoVisible = true;
},
fileUpload() {
uploadIframe((file) => {
this.uploadFile({file})
})
},
uploadBase64(blob) {
const file = dataURLToFile(blob, (new Date()).getTime() + '.png')
this.uploadFile({file})
this.photoVisible = false;
}
},
mounted() {
const { uploaded } = this;
if (this.uploaded) {
this.fileList.push({
name: uploaded,
url: uploaded
});
}
},
computed: {
isMobile () {
return document.querySelector("body").offsetWidth < 800
},
fileImage() {
if(this.fileList.length) {
return this.fileList[0]['url']
}
return null
}
},
};
</script>
<style lang="scss">
.el-icon-close-tip {
display: none !important;
}
</style>
本文由 邓尘锋 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Nov 29, 2022 at 01:18 pm