一五六、Node+Vue 使用七牛上传图片,并配置个人域名

1. 七牛云ak/sk获取

  1. 点击注册🔗开通七牛开发者帐号
  2. 如果已有账号,直接登录七牛开发者后台,点击这里🔗查看 Access Key 和 Secret Key

2. Node.js获取七牛token

安装qiniu

npm install qiniu

创建空间
在这里插入图片描述

Node获取token

const qiniu = require('qiniu');
const ACCESS_KEY = 'xxx';
const SECRET_KEY = 'xxx';
const mac = new qiniu.auth.digest.Mac(ACCESS_KEY, SECRET_KEY);

const {Auth} = require('@middlewares/auth');
const AUTH_ADMIN = 16;

const {Resolve} = require('@lib/helper');
const res = new Resolve();

const Router = require('koa-router');

const router = new Router({
    prefix: '/api/v1'
});

// 获取token
router.post('/upload/token', new Auth(AUTH_ADMIN).m, async ctx => {
    const options = {
        scope: 'xxx', //你的存储空间名称
        expires: 7200
    };
    const putPolicy = new qiniu.rs.PutPolicy(options);
    ctx.response.status = 200;
    const data = {
        token: putPolicy.uploadToken(mac)
    };
    ctx.body = res.json(data);
});

module.exports = router;

3. Vue获取token并上传图片

获取token

//src/api/upload.js
import request from '@/utils/request';

// 获取上传图片token
export function getToken(params) {
    return request({
        url: '/upload/token',
        method: 'post',
        params
    });
}

<template>
  <section class="wrap">
    <el-form
      ref="ruleForm"
      :model="ruleForm"
      :rules="rules"
      label-width="120px"
      class="demo-ruleForm"
    >
      <el-form-item label="标题" prop="title">
        <el-input v-model="ruleForm.title" />
      </el-form-item>
      <el-form-item label="描述" prop="description">
        <el-input v-model="ruleForm.description" />
      </el-form-item>
      <el-form-item label="SEO关键字" prop="seo_keyword">
        <el-input v-model="ruleForm.seo_keyword" />
      </el-form-item>
      <el-form-item label="图片" prop="img_url">
        <el-upload
          class="avatar-uploader"
          action="https://upload-z0.qiniup.com/"
          :show-file-list="false"
          :data="{ token }"
          :on-success="handleUploadSuccess"
        >
          <img
            v-if="ruleForm.img_url"
            width="80"
            height="80"
            :src="ruleForm.img_url"
            class="avatar"
          />
          <i v-else class="el-icon-plus avatar-uploader-icon" />
        </el-upload>
      </el-form-item>
      <el-form-item label="展示" prop="status">
        <el-radio-group v-model="ruleForm.status">
          <el-radio :label="1">显示</el-radio>
          <el-radio :label="0">隐藏</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="分类" prop="category_id">
        <el-select v-model="ruleForm.category_id" placeholder="请选择分类">
          <el-option
            v-for="item in categoryList"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="排序" prop="sort_order">
        <el-input v-model="ruleForm.sort_order" />
      </el-form-item>
      <el-form-item label="内容" prop="content">
        <mavon-editor
          ref="md"
          v-model="ruleForm.content"
          code-style="atom-one-dark"
          @imgAdd="$imgAdd"
          @imgDel="$imgDel"
        />
      </el-form-item>

      <el-form-item>
        <el-button @click="resetForm('ruleForm')">重置</el-button>
        <el-button type="primary" @click="submitForm('ruleForm')">
          立即创建
        </el-button>
      </el-form-item>
    </el-form>
  </section>
</template>

<script>
import { mapState } from "vuex";
import { create } from "@/api/article";
import { list } from "@/api/category";
import { getToken } from "@/api/upload";
import axios from "axios";

export default {
  name: "CategoryCreate",
  data() {
    return {
      token: "",
      categoryList: [],
      ruleForm: {
        title: "",
        description: "",
        img_url: "",
        seo_keyword: "",
        status: 1,
        sort_order: 1,
        admin_id: "",
        category_id: "",
        content: "",
      },
      rules: {
        title: [{ required: true, message: "请输入文章标题", trigger: "blur" }],
        description: [
          { required: true, message: "请输入文章描述", trigger: "blur" },
        ],
        img_url: [
          { required: true, message: "请输入图片链接", trigger: "blur" },
        ],
        seo_keyword: [
          { required: true, message: "请输入 SEO 关键字", trigger: "blur" },
        ],
        status: [
          { required: true, message: "请输入展示状态", trigger: "blur" },
        ],
        sort_order: [
          { required: true, message: "请输入文章排序", trigger: "blur" },
        ],
        category_id: [
          { required: true, message: "请选择分类", trigger: "blur" },
        ],
        content: [
          { required: true, message: "请输入文章内容", trigger: "blur" },
        ],
      },
    };
  },
  computed: {
    ...mapState({
      adminInfo: (state) => state.admin.adminInfo,
    }),
  },
  mounted() {
    this.$axios = axios.create({ withCredentials: false });
    this.getUploadToken();
    this.getCategoryList();
  },
  methods: {
    // 获取上传token
    async getUploadToken() {
      try {
        const res = await getToken();
        this.token = res.data.token;
      } catch (err) {
        console.log(err);
      }
    },
    // 上传图片成功回调
    handleUploadSuccess(file) {
      console.log("🚀 > handleUploadSuccess > file", file);
      this.ruleForm.img_url = `http://cdn.at-will.cn/${file.key}`;
      this.$message.success("上传成功!");
    },
    // 编辑器删除图片回调
    $imgDel(pos, $file) {
      console.log(pos, $file);
    },
    // 编辑器新增上传图片回调
    $imgAdd(pos, $file) {
      const loading = this.$loading({
        lock: true,
        text: "Loading",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });

      // 第一步.将图片上传到服务器.
      const formdata = new FormData();
      formdata.append("file", $file);
      formdata.append("token", this.token);
      this.$axios({
        url: "https://upload-z0.qiniup.com/",
        method: "post",
        data: formdata,
        headers: { "Content-Type": "multipart/form-data" },
      })
        .then((res) => {
          const img_url = `http://cdn.at-will.cn/${res.data.key}`;
          this.$refs.md.$img2Url(pos, img_url);
          loading.close();
        })
        .catch((err) => {
          console.log(err);
          loading.close();
        });
    },
    // 获取分类列表
    async getCategoryList() {
      try {
        this.listLoading = true;
        const res = await list();
        this.categoryList = res.data.data;
      } catch (err) {
        console.log(err);
      } finally {
        this.listLoading = false;
      }
    },
    // 提交表单
    submitForm(formName) {
      if (this.adminInfo) {
        this.ruleForm.admin_id = this.adminInfo.id;
      }

      this.$refs[formName].validate(async (valid) => {
        if (valid) {
          this.createArticle();
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
    // 重置表单
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    // 创建文章
    async createArticle() {
      try {
        const res = await create(this.ruleForm);
        if (res.code === 200) {
          this.$msgbox
            .confirm("创建成功,是否退出创建文章页面", "提示", {
              confirmButtonText: "确定",
              cancelButtonText: "取消",
              type: "success",
            })
            .then(() => {
              this.$router.push("/article/index");
            });
        }
      } catch (err) {
        this.$message.error(err);
      }
    },
  },
};
</script>

<style scoped lang="scss">
.wrap {
  box-sizing: border-box;
  margin: 24px;
}
</style>
<style>
.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;
}
.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>

4. 七牛云配置域名

  1. 点击七牛cdn 域名管理
  2. 添加域名,并在域名管理解析
  3. 配置域名的 CNAME

域名解析一般要半个小时,解析完要等一下才生效
在这里插入图片描述

上传图片并访问

http://cdn.at-will.cn/Fp30TD1fiuyL00qyuGuiqQwo0hNI

完整代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/803215.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis中数据分片与分片策略

概述 数据分片是一种将数据分割并存储在多个节点上的技术&#xff0c;可以有效提高系统的扩展性和性能。在Redis中&#xff0c;数据分片主要用于解决单个实例存储容量和性能瓶颈的问题。通过将数据分散存储到多个Redis节点中&#xff0c;可以将负载均衡到不同的服务器上&#…

如何使用在线工具将手机相册中的图片转换为JPG格式

我们经常在手机相册中保存大量的图片&#xff0c;无论是家庭聚会的照片还是旅行的瞬间&#xff0c;每一幅图像都承载着珍贵的记忆。然而&#xff0c;有时候我们会遇到图片格式不兼容的问题&#xff0c;尤其是在需要将图片分享到特定平台或编辑时。 例如&#xff0c;某些社交平台…

手机操作系统的沉浮往事

手机操作系统的沉浮往事&#xff08;上&#xff09; 移动终端操作系统&#xff0c;也就是指手机、平板电脑等设备所使用的操作系统。 在移动互联网高度发达的今天&#xff0c;我们使用移动终端操作系统的时长&#xff0c;可能已经远远超过了 Windows 等桌面操作系统。 那么&…

Windows 11预览补丁KB5040527影响火绒驱动加载的解决办法

7 月 11 日&#xff0c;微软更新Windows 11 预览版本补丁 KB5040527&#xff0c;补丁安装后会影响火绒驱动加载导致火绒安全软件服务异常&#xff0c;补丁相关信息如下&#xff1a; https://blogs.windows.com/windows-insider/2024/07/11/releasing-windows-11-builds-22621-…

Apache trino的ldap认证开启

作者&#xff1a;櫰木 1、背景 由于trino 默认没有开启用户认证体系&#xff0c;需要ldap用户进行认证。开启tls和ldap用户认证&#xff0c;提高安全性。 2、配置 前置条件。 trino 集群已经部署完成 ldap 服务 openjdk 版本大于11.0.17 生成证书 keytool -genkeypair…

Python(集合)

集合中只能存储不可变类型&#xff0c;使用{}定义&#xff0c;元素之间用逗号分隔 #集合的使用 #方法1 s{10,20,30,40} #整数是不可变数据类型,不能存储列表 print(s) #方法2 sset()#创建了一个空集合 print(s) s{}#创建了一个字典 print(s,type(s))sset(helloworld) print(s)…

UNiapp微信小程序Ucharts

效果图如下 以上为加载接口所得数据的玫瑰图与折线图 具体步骤如下 1&#xff0c;将插件导入Hbuiler 所需要的项目中&#xff08;插件地址&#xff1a;秋云 ucharts echarts 高性能跨全端图表组件 - DCloud 插件市场&#xff09; 2&#xff0c;导入成功是这样的 3&#xff0c…

镜舟科技荣获优秀数字化服务商奖,助力企业用数智技术重塑新消费

7 月 13 日&#xff0c;由 ITShare智享会和 BT商业科技观察主办的2024 第八届 FMCG 零售消费品数字化峰会于上海落幕。在现场&#xff0c;镜舟科技凭借在多家零售企业构建与实施智能数据中台解决方案的成功经验&#xff0c;荣获优秀数字化服务商奖项。 在会上&#xff0c;麦当劳…

软件测试——web单功能测试

工作职责&#xff1a; 1.负责产品系统测试&#xff0c;包括功能测试、性能测试、稳定性测试、用户场景测试、可靠性测试等。 2.负责测试相关文档的编写&#xff0c;包括测试计划、测试用例、测试报告等。 3.负责自动化测试框架、用例的维护。 岗位要求&#xff1a; 1.熟练…

无编码器多模态大模型EVE:原生多模态新方案

近期&#xff0c;关于多模态大模型的研究如火如荼&#xff0c;工业界的投入也愈发高涨。国外相继推出了炙手可热的模型&#xff0c;例如 GPT-4o &#xff08;OpenAI&#xff09;、Gemini&#xff08;Google&#xff09;、Phi-3V &#xff08;Microsoft&#xff09;、Claude-3V&…

SpringMVC框架--个人笔记步骤总结

一、步骤 1.创建工程 2.加入springmvc依赖--pom.xml <!--springmvc依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.10.RELEASE</version> </depend…

jenkins系列-07.轻易级jpom安装

jpom是一个容器化服务管理工具&#xff1a;在线构建&#xff0c;自动部署&#xff0c;日常运维, 比jenkins轻量多了。 本篇介绍mac m1安装jpom: #下载&#xff1a;https://jpom.top/pages/all-downloads/ 解压&#xff1a;/Users/jelex/Documents/work/jpom-2.10.40 启动前修…

C语言 ——— 编写代码,判断 整型数组 是否 有序

目录 题目要求 代码实现 题目要求 判断 整型数组 是否有序 如果 整型数组 有序输出 sorted&#xff1b;否则输出 unsorted 代码实现 #include<stdio.h> int main() {int arr[10] { 0 };int sz sizeof(arr) / sizeof(arr[0]);//输入for (int i 0; i < sz; i){s…

Large Language Model系列之一:语言模型与表征学习(Language Models and Representation Learning)

语言模型与表征学习&#xff08;Language Models and Representation Learning&#xff09; 1 语言模型 N-Gram模型 from collections import defaultdictsentences [The swift fox jumps over the lazy dog.,The swift river flows under the ancient bridge.,The swift br…

分页查询

1 基础分页 1.1需求分析 我们之前做的查询功能&#xff0c;是将数据库中所有的数据查询出来并展示到页面上&#xff0c;试想如果数据库中的数据有很多(假设有十几万条)的时候&#xff0c;将数据全部展示出来肯定不现实&#xff0c;那如何解决这个问题呢&#xff1f; 使用分页…

【网络安全】PostMessage:分析JS实现XSS

未经许可&#xff0c;不得转载。 文章目录 前言示例正文 前言 PostMessage是一个用于在网页间安全地发送消息的浏览器 API。它允许不同的窗口&#xff08;例如&#xff0c;来自同一域名下的不同页面或者不同域名下的跨域页面&#xff09;进行通信&#xff0c;而无需通过服务器…

中转程序理解

P1S SRV ParserCfgFile解析配置文件&#xff08;由ATS.XML---->ATS.BIN&#xff09; CCHandler 循环调用接口&#xff0c;继承于CycleSchInterface 继承于DcsHandler800&#xff0c;收发DCS报文 继承于MsgProcessor&#xff0c;好像 收发同步消息有关 继承于DcsLogMana…

微软的vscode和vs2022快捷键官网链接

vscode官方文档:https://code.visualstudio.com/docs/ vscode快捷键官方文档:https://code.visualstudio.com/docs/getstarted/keybindings vs2022官方文档:https://learn.microsoft.com/zh-cn/visualstudio/ide/?viewvs-2022 vscode快捷键官方文档:https://learn.microsoft.c…

论文学习——基于自适应选择的动态多目标进化优化有效响应策略

论文题目&#xff1a;Effective response strategies based on adaptive selection for dynamic multi-objective evolutionary optimization 基于自适应选择的动态多目标进化优化有效响应策略&#xff08;Xiaoli Li a,b,c, Anran Cao a,∗, Kang Wang a&#xff09;Applied S…

MongoDB常用命令大全,概述、备份恢复

文章目录 一、MongoDB简介二、服务启动停止、连接三、数据库相关四、集合操作五、文档操作六、数据备份与恢复/导入导出数据6.1 mongodump备份数据库6.2 mongorestore还原数据库6.3 mongoexport导出表 或 表中部分字段6.4 mongoimport导入表 或 表中部分字段 七、其他常用命令八…