vue 纯前端对接阿里云oss文件上传封装,支持批量多文件上传,粘贴上传和拖拽上传,大文件上传时拿到上传进度。

发布于:2024-12-18 ⋅ 阅读:(128) ⋅ 点赞:(0)

使用阿里云上传先看官方文档(阿里云官方文档
我这边只做了简单上传和分片上传,也包含了粘贴上传和拖拽上传。

1.首页先安装

npm i ali-oss

2.在utils下创建uploadOss.js

const OSS = require('ali-oss')
import { getOsstoken } from '@/api/index'
//把file文件转为base64
function getBase64(file) {
    return new Promise((resolve, reject) => {
        ///FileReader类就是专门用来读文件的
        const reader = new FileReader()
        //开始读文件
        //readAsDataURL: dataurl它的本质就是图片的二进制数据, 进行base64加密后形成的一个字符串,
        reader.readAsDataURL(file)
        // 成功和失败返回对应的信息,reader.result一个base64,可以直接使用
        reader.onload = () => resolve(reader.result)
        // 失败返回失败的信息
        reader.onerror = error => reject(error)
    })
}
//获取文件大小
function getfileSize(val) {
    if (val === 0) return "0 B"
    var k = 1024;
    var sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
    let i = Math.floor(Math.log(val) / Math.log(k))
    return ((val / Math.pow(k, i)).toFixed(2) + "" + sizes[i])
}
//时间格式转换
function parseTime(time, pattern) {
    if (arguments.length === 0 || !time) {
        return null
    }
    const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
    let date
    if (typeof time === 'object') {
        date = time
    } else {
        if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
            time = parseInt(time)
        } else if (typeof time === 'string') {
            time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
        }
        if ((typeof time === 'number') && (time.toString().length === 10)) {
            time = time * 1000
        }
        date = new Date(time)
    }
    const formatObj = {
        y: date.getFullYear(),
        m: date.getMonth() + 1,
        d: date.getDate(),
        h: date.getHours(),
        i: date.getMinutes(),
        s: date.getSeconds(),
        a: date.getDay()
    }
    const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
        let value = formatObj[key]
        // Note: getDay() returns 0 on Sunday
        if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
        if (result.length > 0 && value < 10) {
            value = '0' + value
        }
        return value || 0
    })
    return time_str
}
//阿里云分片上传
function uploadOssMultipart(file, options) {
    return new Promise(async (resolve, reject) => {
        getOsstoken().then(res => {
            if (res.code == 1) {
                const client = new OSS({
                    secure: res.data.secure, // 上传链接返回支持https
                    region: res.data.region, // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
                    accessKeyId: res.data.AccessKeyId,
                    accessKeySecret: res.data.AccessKeySecret,
                    bucket: res.data.bucket, // 填写Bucket名称
                    stsToken: res.data.SecurityToken //上传token
                })
                 //  唯一的文件名这个规则需要在阿里云哪里配置好
                const fileName = '/uploads/' + parseTime(file.lastModifiedDate, '{y}{m}{d}/') + file.fileName + file.lastModified
                resolve(client.multipartUpload(fileName, file.file, { ...options }))
            }
        })

    })
}
//阿里云普通上传
function uploadOssPut(file) {
    return new Promise(async (resolve, reject) => {
        getOsstoken().then(res => {
            if (res.code == 1) {
                const client = new OSS({
                    secure: res.data.secure, // 上传链接返回支持https
                    region: res.data.region, // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
                    accessKeyId: res.data.AccessKeyId,
                    accessKeySecret: res.data.AccessKeySecret,
                    bucket: res.data.bucket, // 填写Bucket名称
                    stsToken: res.data.SecurityToken
                })
                const fileName = '/uploads/' + parseTime(file.lastModifiedDate, '{y}{m}{d}/') + file.name
                //  配置路径以及文件名称
                resolve(client.put(fileName, file))
            }
        })

    })
}
export { uploadOssPut, uploadOssMultipart,getfileSize,getBase64}


3.普通上传方法使用

import { uploadOssPut } from '@/utils/uploadOss.js';

<div class="btn" @click="setAvatar">修改头像</div>
<input type="file" ref="file" style="display: none;" v-on:change="handleDrop($event)">
setAvatar() {
   this.$refs.file.click()
},
async handleDrop(e) {
  let files = e.target.files[0]
  let url = await uploadOssPut(files)
  saveUserInfo({ avatar: '/' + url.name }).then(res => {
    if (res.code == 1) {
       this.$modal.msgSuccess(`头像已修改`);
       this.getuser()
    }
  })
},

4.分片上传以及拿到上传进度支持多文件

在这里插入图片描述

<template>
    <div>
        <input type="file" multiple ref="file" style="display: none;" v-on:change="handleUpload($event)">
        <div @click="getFile">
            点击上传
        </div>

        <div v-if="isupload">
            <div v-for="(item, index) in filelist " :key="index" style="display: flex;margin-bottom:10px">
                <div>{{ item.fileName }}</div>
                <div style="margin:0px 10px;width:100px">{{ item.fileSize }}</div>
                <el-progress style="width:150px" :text-inside="true" :stroke-width="20"
                    :percentage="item.progress"></el-progress>
            </div>
        </div>
    </div>
</template>

<script>
import { uploadOssMultipart, getfileSize } from '@/utils/uploadOss.js';
export default {
    name: '',
    data() {
        return {
            filelist: [],
            isupload: false,
            nowlist: []
        }
    },
    methods: {
        getFile() {
            this.$refs.file.click()
        },
        handleUpload(e) {
            let files = e.target.files
            for (let i = 0; i < files.length; i++) {
                let obj = {
                    file: files[i],
                    fileName: files[i].name,
                    fileSize: getfileSize(files[i].size),
                    lastModifiedDate: files[i].lastModifiedDate,
                    progress: 0
                }
                this.filelist.push(obj)
            }
            this.uploadOss()
        },
        async uploadOss() {
            console.log(this.filelist);

            this.filelist.forEach(item => {
                const options = {
                    // 获取分片上传进度、断点和返回值。
                    progress: (p, cpt, res) => {
                        item.progress = Number((p * 100).toFixed(0));//进度条
                    },
                    // 目前不传Content-Type 发现会出现错误,具体原因不清除
                    headers: {
                        'Content-Type': 'Content-Type(Mime-Type)'
                    },
                    partSize: 1024 * 1024 * 1,
                };
                this.isupload = true
                uploadOssMultipart(item, options).then(res => {
                    var url = ''
                    let index = res.res.requestUrls[0].indexOf("?");
                    if (index == -1) {
                        url = res.res.requestUrls[0]
                    } else {
                        url = res.res.requestUrls[0].substring(0, index)
                    }
                    this.$refs.file.value = ''
                    this.nowlist.push(url)
                    console.log(this.nowlist, '22222');

                })
            })
        },
    },
}
</script>
<style lang='scss' scoped></style>

5.支持拖拽粘贴上传

拖拽和复制与点击上传区别不大,只是拿到file时的位置不同。

 <input type="textarea" style="width: 300px;height:200px;border:1px solid #eee" @drop.prevent="handleUpload" @paste.prevent="handleUpload">
        handleUpload(e) {
            let files;
            if (e.type == 'drop') {//拖拽
                e.preventDefault()
                files = e.dataTransfer.files;
            } else if (e.type == 'paste') {//复制
                files = e.clipboardData.files;
            } else if (e.type == 'change') { //点击
                files = e.target.files
            }
            for (let i = 0; i < files.length; i++) {
                let obj = {
                    file: files[i],
                    fileName: files[i].name,
                    fileSize: getfileSize(files[i].size),
                    lastModifiedDate: files[i].lastModifiedDate,
                    progress: 0
                }
                this.filelist.push(obj)
            }
            this.uploadOss()
        },

网站公告

今日签到

点亮在社区的每一天
去签到