前言
项目将数据与应用混在一起,不利于对系统进行维护。可以考虑如下场景:
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 版权协议,转载请附上原文出处链接和本声明。