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

news2024/11/13 7:57:12

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

完整代码

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在SpringCloud中如何轻松实现微服务间的通信

在Spring Cloud中&#xff0c;实现微服务间的通信非常简单。Spring Cloud提供了多种方式来进行微服务之间的通信&#xff0c;包括使用RestTemplate、Feign、Ribbon、Eureka等组件。下面我将详细介绍这些方式的使用方法。 使用RestTemplate进行通信&#xff1a; RestTemplate是S…

ECCV2024|GLAD:利用全局和局部自适应扩散模型实现更好的无监督异常检测重建

GLAD&#xff1a;利用全局和局部自适应扩散模型实现更好的无监督异常检测重建 论文标题&#xff1a;GLAD: Towards Better Reconstruction with Global and Local Adaptive Diffusion Models for Unsupervised Anomaly Detection 论文地址&#xff1a;https://arxiv.org/abs/2…

字符串类中的常用方法

1 string对象的创建 静态创建 String s1  "abc";  String s2  "abc";  动态创建 String s3  new String("abc"); String s4  new String("abc"); 2string对象的不可变性 任何一个String对象在创建之后都不能对它的…

blender中设置物体的中心到某个顶点

方式一&#xff1a; 1&#xff0c;首先选中物体&#xff0c; 2&#xff0c;选中编辑模式&#xff0c; 3&#xff0c;选中点模式&#xff0c;并选择物体的一个顶点 4&#xff0c;鼠标点击右键---- 吸附至像素点--游标->选中项&#xff0c;这样&#xff0c;游标移动到了选中…

PulsarClient源码解析

一、Pulsar客户端简析 pulsar服务是经典的C/S架构&#xff0c;由客户端和服务端构成。服务端提供处理读写请求服务&#xff0c;客户端负责发起读写请求。pulsar将客户端按照读写分成了生产者和消费者&#xff0c;但是无论怎么分&#xff0c;它们本质上都是Pulsar客户端并有很多…

QT--控件篇四

一、对话框 在软件开发中&#xff0c;对话框&#xff08;Dialog&#xff09;是一种常见的用户界面元素&#xff0c;用于与用户进行交互和获取信息。它通常以模态或非模态的形式出现&#xff0c;模态对话框会阻止用户与应用程序的其他部分交互&#xff0c;直到对话框关闭为止&a…

快速排序(quick sort)

欢迎来到一夜看尽长安花 博客&#xff0c;您的点赞和收藏是我持续发文的动力 对于文章中出现的任何错误请大家批评指出&#xff0c;一定及时修改。有任何想要讨论的问题可联系我&#xff1a;3329759426qq.com 。发布文章的风格因专栏而异&#xff0c;均自成体系&#xff0c;不足…

nftables(9)NAT、FLOWTABLES

NAT NAT简介 我们在iptables、firewalld中都介绍过有关NAT的相关部分。那么在nftables中&#xff0c;我们继续介绍nftables中NAT的功能实现方式&#xff0c;配置方法和与前两者的区别。 我们先简单回顾一下NAT的类型和其功能&#xff1a; 这些是不同的网络地址转换&#xf…

在 Windows 上开发.NET MAUI 应用_1.安装开发环境

开发跨平台的本机 .NET Multi-platform App UI (.NET MAUI) 应用需要 Visual Studio 2022 17.8 或更高版本&#xff0c;或者具有 .NET MAUI 扩展的最新 Visual Studio Code。要开始在 Windows 上开发本机跨平台 .NET MAUI 应用&#xff0c;请按照安装步骤安装 Visual Studio 20…

leetcode94. 二叉树的中序遍历,递归法+迭代法。附带前序遍历方法

leetcode94. 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; …

高职综合布线实训室

一、高职综合布线实训室建设背景 随着《国民经济和社会发展第十四个五年规划和2035年远景目标纲要》的深入实施&#xff0c;数字化转型已成为国家发展的核心战略之一&#xff0c;计算机网络技术作为数字化建设的基石&#xff0c;其重要性日益凸显。然而&#xff0c;面对数字时代…

【手撕RLHF-DPO(1)】不是PPO训不起,而是DPO更有性价比!

Introduction Direct Preference Optimization: Your Language Model is Secretly a Reward Model 在LLM对齐问题上&#xff0c;OpenAI提出的RLHF训练范式最为人熟知&#xff0c;同时也是ChatGPT行之有效的对齐方案。 RLHF通常包含三个步骤&#xff1a;SFT, Reward Model, PPO…

【STM32】RTT-Studio中HAL库开发教程三:IIC通信--AHT20

文章目录 一、I2C总线通信协议二、AHT20传感器介绍三、STM32CubeMX配置硬件IIC四、RTT中初始化配置五、具体实现代码六、实验现象 一、I2C总线通信协议 使用奥松的AHT20温湿度传感器&#xff0c;对环境温湿度进行采集。AHT20采用的是IIC进行通信&#xff0c;可以使用硬件IIC或…

Visual Studio使用——在vs中给vb.net项目添加新的窗口:新建的方式、添加已有窗口的方式

目录 引出Visual Studio使用vb添加新的窗体自定义代码片段vs显示所有文件 总结Idea安装和使用0.Java下载 和 IDEA工具1.首次新建项目2.隐藏文件不必要显示文件3.目录层级设置4.Settings设置选择idea的场景提示代码不区分大小写 取消git的代码作者显示 引出 Visual Studio使用—…

trl - 微调、对齐大模型的全栈工具

文章目录 一、关于 TRL亮点 二、安装1、Python包2、从源码安装3、存储库 三、命令行界面&#xff08;CLI&#xff09;四、如何使用1、SFTTrainer2、RewardTrainer3、PPOTrainer4、DPOTrainer 五、其它开发 & 贡献参考文献最近策略优化 PPO直接偏好优化 DPO 一、关于 TRL T…

安全防御,防火墙配置NAT转换智能选举综合实验

目录&#xff1a; 一、实验拓扑图 二、实验需求 三、实验大致思路 四、实验步骤 1、防火墙的相关配置 2、ISP的配置 2.1 接口ip地址配置&#xff1a; 3、新增设备地址配置 4、多对多的NAT策略配置&#xff0c;但是要保存一个公网ip不能用来转换&#xff0c;使得办公区的…

c++入门----类与对象(上)

大家好啊&#xff0c;好久没有更新了。因为本人的愚笨&#xff0c;想与大家分享的话肯定还得自己明白了才能给大家分享吧。所以这几天都在内部消化。好给大家优质的文章。当然我写的肯定还是很有问题的&#xff0c;希望大家可以在评论区里面指出来。好&#xff0c;废话不多说&a…

LabVIEW 与 PLC 通讯方式

在工业自动化中&#xff0c;LabVIEW 与 PLC&#xff08;可编程逻辑控制器&#xff09;的通信至关重要&#xff0c;常见的通信方式包括 OPC、Modbus、EtherNet/IP、Profibus/Profinet 和 Serial&#xff08;RS232/RS485&#xff09;。这些通信协议各有特点和应用场景&#xff0c…

从图表访问Data Store Memory

Simulink模型将全局变量实现为数据存储&#xff0c;可以是数据存储内存块&#xff0c;也可以是Simulink.Signal的实例。您可以使用数据存储在多个Simulink块之间共享数据&#xff0c;而无需显式的输入或输出连接来将数据从一个块传递到另一个块。Stateflow图表通过符号化地读取…

警惕预言成真!3本预警、On Hold已被剔除,新增8本SCI/SSCI被除名!7月WOS更新(附下载)

本周投稿推荐 SCI • 能源科学类&#xff0c;1.5-2.0&#xff08;25天来稿即录&#xff09; • IEEE计算机类&#xff0c;4.0-5.0&#xff08;48天录用&#xff09; • 生物医学制药类&#xff08;2天逢投必中&#xff09; EI • 各领域沾边均可&#xff08;2天录用&…