JS+Vue 自定义文件上传 + Vue Upload 封装

in 前端 with 0 comment

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>
Comments are closed.