Vue 使用云存储(七牛云)

  • Post author:
  • Post category:vue


前言

项目将数据与应用混在一起,不利于对系统进行维护。可以考虑如下场景:

1、希望通过 CDN 加速来提高图片资源的访问速度

2、服务器存储满了,需要多图片等文件资源做迁移,但是服务不能中断,域名不能变化 …

通过数应分离思想,就可以解决以上问题。 几乎所有系统都会涉及到图片、视频等资源的上传和管理;项目中使用存储图片、视频的云存储 数应分离后,可以将图片等文件资源独立出来,存储到云端。常见的云有阿里云、腾讯云、 华为云、七牛云等。本次以七牛云提供的 OSS 存储服务为基础,通过 Node 搭建后 端业务服务器,通过 Vue 构建用户端。

服务端:

app.js

const express = require('express')
const app = express();
const qiniu = require('./qiniu')

// 创建上传凭证
app.get('/token', (req, res) => {
    let token = new qiniu().uploadToken();
    // console.log(token);
    res.status(200).send(token);
})
// app.post('/deletes',(req,res)=>{

// })

app.get('/test', (req, res) => {
    let result = {
        msg: 'ok'
    }
    res.send(result)
})
app.listen(3000, () => {
    console.log('server running at http://127.0.0.1:3000');
})

qiniu.js

const sdk = require('qiniu');
// https://developer.qiniu.com/kodo/1289/nodejs
class qiniu {
    constructor() {
        this.accessKey = '';//此处填写公钥
        this.secretKey = '';//私钥
        this.options = {
            scope: 'leviash',
            expires: 7200
        }
    }
    //创建上传凭证
    uploadToken() {
        let mac = new sdk.auth.digest.Mac(this.accessKey, this.secretKey);
        let putPolicy = new sdk.rs.PutPolicy(this.options);
        let uploadToken = putPolicy.uploadToken(mac);
        return uploadToken;
    }

    // deleteFile() {
    //     let mac = new qiniu.auth.digest.Mac(this.accessKey, this.secretKey);
    //     let config = new qiniu.conf.Config();
    //     //config.useHttpsDomain = true;
    //     config.zone = qiniu.zone.Zone_z2; // 华南
    //     let bucketManager = new sdk.rs.BucketManager(mac, config);

    //     let bucket = 'leviash';
    //     let key = 'fileWed Nov 16 2022 19:52:12 GMT+0800 (中国标准时间)54.';// 传递文件名

    //     bucketManager.delete(bucket, key, function (err, respBody, respInfo) {
    //         if (err) {
    //             console.log(err);
    //             //throw err;
    //         } else {
    //             console.log(respBody, respInfo) // 最后还是res.end
    //         }
    //     });
    // }
}
module.exports = qiniu

运行服务端

node app

客户端:

组件QiNiuUpload.vue

<template>
    <div>
        <!-- 七牛云上传 -->
        <!-- https://element.eleme.cn/#/zh-CN/component/upload -->
        <el-upload class="avatar-uploader" :action="domain" :auto-upload="false" :on-change="fileChange"
            :file-list="fileList">
            <img v-if="imageUrl" :src="imageUrl" class="avatar" id="imgae" />
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        </el-upload>
        <el-button type="primary" v-on:click="upload()">上传文件</el-button>
        <el-button type="primary" v-on:click="deleteFile()">删除文件</el-button>
    </div>
</template>


<script>

// https://developer.qiniu.com/kodo/1283/javascript
export default {
    name: 'QiniuUpload',
    data() {
        return {
            fileList: [],
            imageUrl: '',
            // 七牛云的上传地址,根据自己所在地区选择,我这里是华南区
            domain: "http://upload.qiniup.com",
            // 这是七牛云空间的外链默认域名
            qiniuaddr: "",
            file: null,
        }
    },
    methods: {
        fileChange(file) {
            this.fileList.push(file.raw);
            this.file = file.raw;
            console.log(this.fileList);
        },
        // 验证文件合法性
        beforeUpload(file) {
            if (!file) {
                this.$message.error("请选择图片!");
                return false;
            }
            const isJPG = file.type === "image/jpeg" || file.type ===
                "image/png";
            const isLt2M = file.size / 1024 / 1024 < 2;
            if (!isJPG) {
                this.$message.error("上传头像图片只能是 JPG 格式!");
            }
            if (!isLt2M) {
                this.$message.error("上传头像图片大小不能超过 2MB!");
            }
            return isJPG && isLt2M;
        },

        // 上传文件到七牛云
        upqiniu() {
            if (!this.beforeUpload(this.file)) {
                return;
            }
            this.$http.request('/api/token').then(res => {
                // 组装数据,上传七牛云
                const formdata = new FormData();
                formdata.append("file", this.file);
                formdata.append("token", res.data);
                // 重命名要上传的文件
                let filetype = "";
                const keyname = "file" + new Date() +
                    Math.floor(Math.random() * 100) + "." + filetype;
                formdata.append("key", keyname);
                const config = {
                    headers: { "Content-Type": "multipart/form-data" },
                };
                // 获取到凭证之后再将文件上传到七牛云空间
                let that = this;
                this.$http.post(this.domain, formdata, config).then((res) => {
                    // console.log(res);
                    that.imageUrl = "http://" + this.qiniuaddr + "/" +
                        res.data.key;
                    that.$message({
                        message: "上传成功",
                        type: "success",
                    });
                })
                    .catch((err) => {
                        console.log(err);
                    });

            })
                .catch(err => {
                    console.log(err);
                })
        },
        // 上传按钮
        upload() {
            this.upqiniu();
        },
        //删除按钮
        // deleteFile() {
        //     console.log(file,fileList);
        //     deletes('/api/delete').then((res)=>{
        //         console.log(res);
        //     })
        // }
    }
}


</script>

<style>
/* 不能有 scoped 否则 element-ui 样式不生效*/
.avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
}

.avatar-uploader .el-upload:hover {
    border-color: #409EFF;
}

/* 让+居中 */
.el-upload .el-icon-plus {
    line-height: 178px;
}

.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
}

.avatar {
    width: 178px;
    height: 178px;
    display: block;
}
</style>

App.vue配置

<template>
  <div id="app">
  <!-- <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/> -->
  <QiniuUpload/>
  </div>
  </template>
  <script>
  // import HelloWorld from './components/HelloWorld.vue'
  import QiniuUpload from './components/QiniuUpload.vue'
  export default {
  name: 'App',
  components: {
  // HelloWorld
  QiniuUpload,
  }
  }
  </script>
  <style>
  #app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  }
  </style>

main.js

import Vue from 'vue'
import App from './App.vue'
// 引入 element-ui
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// 挂载 axios
import Axios from 'axios'
// Axios.defaults.baseURL='http://localhost:3000';
Vue.prototype.$http=Axios;
Vue.use(ElementUI)
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

运行

运行客户端

上传成功



版权声明:本文为qq_51588894原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。