1、效果展示

2、实现代码

在components目录下,新建组件 myImgUpload.vue,代码如下:

<template>
    <div>
        <el-upload
            :class="disabled ? 'hideAdd' : 'showAdd'"
            ref="myImgUpload"
            list-type="picture-card"
            :multiple="limit > 1"
            :disabled="disabled"
            :file-list="fileList"
            :accept="accept"
            :limit="limit"
            :on-exceed="onExceed"
            :action="action"
            :data="params"
            :before-upload="beforeUpload"
            :on-success="onSuccess"
            :on-remove="onRemove"
            :on-error="onError"
            :on-preview="onPreview"
            :with-credentials="true">
            <i class="el-icon-plus"></i>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible" append-to-body>
            <img width="100%" :src="dialogImageUrl" alt="">
        </el-dialog>
        <div v-if='tip' class="tip">{{tip}}</div>
    </div>
</template>

<script>
    export default {
        props: {
            action: {
                type: String,
                default: `${window.baseUrl}web/upload/getAvatarUploadInfo`
            },
            value: {
                type: String,
                default: ''
            },
            fileList: null,
            isEdit: {
                type: Boolean,
                default: false
            },
            tip: {
                type: String,
                default: ''
            },
            disabled: {
                type: Boolean,
                default: false
            },
            // 限制上传数量,默认是1张
            limit: {
                type: Number,
                default: 1
            },
            // 限制上传大小,默认是5M
            maxsize: {
                type: Number,
                default: 5
            },
            // 限制上传文件格式,默认是1 - 图片
            // 文件类型:1:图片(.jpg/.png) ;2:so文件/txt文件上传(.so/.txt);3:provision文件上传(.mobileprovision)
            fileType: {
                type: Number,
                default: 1
            }
        },
        data() {
            return {
                params: {
                    'fileType': 1,
                    'fileName': 'default.jpg'
                },
                dialogImageUrl: '',
                dialogVisible: false,
                accept: ''
            }
        },
        created() {
            switch (this.fileType) {
            case 1:
                this.accept = 'image/*'
                break
            default:
                this.accept = '*'
            }
        },
        methods: {
            uploadAliyun(res, file) {
                if (res.code === '000') {
                    let objectName = res.data.key
                    let OSS = require('ali-oss')
                    let client = new OSS({
                        region: res.data.regionId,
                        accessKeyId: res.data.accessKeyId,
                        accessKeySecret: res.data.accessKeySecret,
                        stsToken: res.data.securityToken,
                        bucket: res.data.bucket
                    })
                    const put = async() => {
                        try {
                            let result = await client.put(objectName, file.raw)
                            if (result.res.statusCode === 200) {
                                console.log('上传阿里云成功')
                                // this.$message.success('上传成功')
                            } else {
                                this.$message.error('上传阿里云失败')
                            }
                        } catch (e) {
                            this.$message.error(e)
                        }
                    }
                    put()
                } else {
                    this.$message.error(res.message)
                }
            },
            clearFiles () {
                this.$refs.myImgUpload.clearFiles()
            },
            beforeUpload(file) {
                this.params.fileName = file.name
                const isJPG = file.type === 'image/jpeg'
                const isPNG = file.type === 'image/png'
                const isRightSize = file.size / 1024 / 1024 < this.maxsize
                if (!isJPG && !isPNG) {
                    this.$message.error('上传头像图片只能是 JPG 或 PNG 格式!')
                }
                if (!isRightSize) {
                    this.$message.error('上传图片大小不能超过最大限制!')
                }
                return (isJPG || isPNG) && isRightSize
            },
            onSuccess(res, file, fileList) {
                this.$message.success('上传成功')
                let val = ''
                fileList.forEach(item => {
                    if (val !== '') {
                        val += ','
                    }
                    if (item.response) {
                        val += item.response.data.downloadPath
                    } else {
                        val += item.url
                    }
                })
                this.$emit('input', val)
                this.uploadAliyun(res, file)
            },
            onPreview(file) {
                this.dialogImageUrl = file.url
                this.dialogVisible = true
            },
            onExceed(files, fileList) {
                this.$message({
                    message: '上传数量超出最大限制!',
                    type: 'warning'
                })
            },
            onRemove(res, fileList) {
                let val = ''
                fileList.forEach(item => {
                    if (val !== '') {
                        val += ','
                    }
                    if (item.response) {
                        val += item.response.data.downloadPath
                    } else {
                        val += item.url
                    }
                })
                this.$emit('input', val)
            },
            onError(err) {
                console.log('this is onError:\n', err)
            }
        }
    }
</script>

<style lang='less' scope>
    .tip {
        color: #606266;
        font-size: 12px;
    }
    .hideAdd {
        .el-upload--picture-card {
            display: none;
        }
    }
    .showAdd {
        .el-upload--picture-card {
            display: block;
        }
    }
</style>

3、设计思路:

在之前的一篇文章中(【上传文件】基于阿里云的视频点播VOD、对象存储OSS实现音视频图片等文件上传),我们用了一个简单的 el-button 结合原生 input 来实现了上传文件至阿里云,但是交互上存在诸多漏洞,比方说我上传了一张图片之后只能替换无法删除;上传成功之后无法预览图片等等。所以,这次我们基于 el-upload 来更好地去实现这个上传功能,交互上也表现地更合理些。

实现的关键在于对 el-upload上传生命周期 的理解,在合适的时间上做合适的事情!比如:在合适的时间(beforeUpload)对文件格式做校验,在合适的时间(onSuccess)上传文件至阿里云OSS,在合适的时间(onSuccess/onRemove)与父组件通信(this.$emit('input', val))。

 

 

 

 

 

 

 

 

Logo

前往低代码交流专区

更多推荐