用七牛云拖拽上传图片,返回图片url或markdown

本文首发于个人博客https://www.kagurakana.xyz/detail/e169338c7,如果对您有帮助,或者任何建议,请务必在小站流言,一起做朋友呀~~

图床介绍

图床是我这种小博客赖以生存的工具,他可以托管图片,减轻我的1核2g的辣鸡服务器的压力.目前我使用过的图床有sm.ms,和七牛cdn,而七牛不只可以托管图片,还可以托管各种静态资源,例如音频和视频等.并为其绑定加速域名.以下主要介绍七牛JavaScript-sdknode-sdk.因为本博客采用了node作为后端.

十分鸡肋的是七牛cdn每个月只有10g的静态资源存储空间(不累加),用超出去会每个月交钱(10G大概1.5元,如果每个月存储100G也就15块),其他的作为小站来说基本不可能达到,具体资费请参照官网.

chrome_iGMDgPtqFk.png

准备工作

1. 注册七牛账号,创建存储空间bucket

首先选择对象存储,并创建存储空间.

chrome_tPsQSMPhwU.png

点击新建空间,进行一些简单的配置,如选择存储地理位置等,配置完成后就会看到下面的存储空间,此时已经可以手动添加图片进去了.

chrome_spZdtbGhRT.png

2. 绑定域名加速

在创建好bucket也就是存储空间之后,可以进行域名加速绑定,好处是可以使用自己的域名进行图片获取和上传.


chrome_o0NX6vqF8Y.png

绑定的域名需要在大陆进行ICP备案,我的域名是kagurakana.xyz,在阿里云购买,SSL证书是阿里云免费个人版证书,这种证书只支持单域名,不支持泛域名(*.domain.com),如果你和我一样需要https协议来存储你的图片,除了本站域名(kagurakana.xyz)需要申请SSL证书之外,cdn域名(我的是cdn.kagurakana.xyz,可以在阿里云的dns解析中配置)也要申请SSL证书,假设你现在已经有了yourdomain.comcdn.yourdomain.com的ssl证书.且主站yourdomain.com已经在域名购买商的dns解析中和Nginx服务器中完成了配置(如何在主站中配置https和Nginx部署SSL我会在最近写一篇文章介绍),那么只需要关注cdn.yourdomain.com的证书就好了,这个不需要进行配置,只要下载下来复制到七牛cdn中就好了,我会在后面介绍.

2.1 配置七牛云域名加速

chrome_WYiIb788pk.png

可以按照喜好自行配置.

2.2 *申请该域名的SSL(HTTPS需要/HTTP可跳过)

在阿里云申请个人免费版SSL证书,填写证书域名为cdn.yourdomain.com,其他默认就好,证书文件会自动关联到到你的cdn域名下.下载Nginx版的证书文件,其中会有一个.pem文件和一个.key文件.先保存在本地.

2.3 *在七牛CDN导入证书文件(HTTPS需要/HTTP可跳过)

chrome_MPTjJAsOaU.png

把刚才先下载的.pem中的内容用编辑器打开,复制到证书内容一栏,把.key文件打开复制到证书密钥一栏,点添加.添加完成后应该可以看到cdn页面下的https证书多了一个可以选的,选择那个.

chrome_a04alRhV4K.png

后面的原站配置选择七牛云存储,其他选择默认或者推荐就好.在高级配置中可选择域名防盗链,防止被引用过多产生更多费用,我配置了本站(kagurakana.xyz)和简书和七牛云这三个.

2.4 配置阿里云域名的DNS解析

在七牛的cdn配置完之后,要将图片cdn和主站DNS进行关联,在七牛完成之后,可以得到一个CNAME值,复制这个CNAME


chrome_FCmpI6O6RS.png

上到阿里云的控制台,找到DNS,记录类型选择CNAME,将刚才的CNAME填入下面的记录字中.

chrome_7pur89ofNn.png

等待DNS服务器更新(TTL时间)后,可以看到状态从等待CNAME成为了成功.

chrome_5AFyqj141Y.png

至此,准备阶段的工作全部完成,你可以用你自定义的域名来访问上传的图片了,然而这是不够的.我们还要解决图片拖拽自动上传的功能.

使用JavaScript-SDK和node-SDK完成自动上传

node-SDK文档

js-SDK文档

1. 后端鉴权

安装七牛cdn

npm install qiniu --save

创建qiniu.config.js文件:

// /config/qiniu.config.js
module.exports = {
  accessKey: '在七牛个人信息密钥管理中可以找到',
  secretKey: '在七牛个人信息密钥管理中可以找到',
  domain: '在bucket管理界面可以找到,可以看下面的图片',
  options: {
    scope: "kagurakana",//你的bucket空间的名称
    expires: 3 * 3600,//单次鉴权有效期,在申请鉴权的多少喵内可以上传,可缺省,默认为1小时

//自定义返回参数,在上传成功后返回给前端,注意是字符串类型,是$()小括号不是大括号,大括号没试过不知道行不行.
//其中$(key),$(bucket),$(fname)是七牛中的默认变量
//
    returnBody: `{"key":"$(key)",
                 "bucket":"$(bucket)",
                 "name":"$(fname)"}`
  }
}
chrome_771RGGm0ZZ.png

更详细的配置可以在官网里找到,这里只列的我的配置.

在router中引入

// /routes/update.js
let express = require('express');
let router = express.Router()

//导入之前的config
let opt = require('../config/qiniu.js')
let qiniu = require('qiniu');

//我自己的管理员权限认证中间件
const {loginCheckAdmin} = require('../midware/midware')

// 定义鉴权对象mac
let mac = new qiniu.auth.digest.Mac(opt.accessKey,opt.secretKey)

// 定义上传凭证
let putPolicy = new qiniu.rs.PutPolicy(opt.options)
let uploadToken = putPolicy.uploadToken(mac)

//处理get获取上传鉴权认证,我这里是管理员才能上传
//你也可以写中间件只能让注册用户上传.或者开放上传(避免滥用不推荐)

router.get('/uptoken',loginCheckAdmin,(req,res,next)=>{
  res.header("Cache-Control", "max-age=0, private, must-revalidate");
  res.header("Pragma", "no-cache");
  res.header("Expires", 0);
  if(uploadToken) {
      res.json({uploadToken});
  }
})


module.exports = router;

后端最简单的配置已经结束了,如果还需要添加文字或图片水印,裁剪图片,加滤镜,生成缩略图,覆盖重复文件可以参考node-SDK文档
.

2. 前端上传

前端使用了vue+axios,可以根据配置自行修改

npm install qiniu-js --save

封装网络请求请求鉴权

//封装网络请求request方法,仅提供参考.
//  network/request.js
import axios from 'axios'
axios.defaults.withCredentials=true;//配置axios携带cookie


export function request(config){
  const instance = axios.create({
    baseURL:'https://yourdomaim.com/apis',
    timeout:5000
  })
//拦截
  instance.interceptors.response.use(res=>{
    if(res.data.errno!=404){
      return res.data;
    }else{
      window.location.replace('/home')
    }
  })
  return instance(config) 
}
// network/imgUpdate.js

import { request } from './request'


export function getUploadToken(){
  return request({
    method:'get',
    url:'你的后端接口/uptoken'
  })
}

拖拽上传

首先来看一下sdk提供的上传函数:

qiniu.upload(file: blob, key: string, token: string, putExtra: object, config: object): observable`

上面的关键函数返回一个观察者对象(observable),该对象具有订阅(subscribe)方法,subscribe方法接收三个函数作为参数,分别在上传中,上传失败,上传成功后调用.

//界面.vue
<template>
  <!-- 监听拖放事件 -->  
  <v-textarea @drop.prevent.stop="imgDrop" v-model="content" label="content"></v-textarea>
</template>

<script>
import { getUploadToken } from "network/imgUpdate";
import * as qiniu from "qiniu-js";

export default {
  name: "BlogPost",
  data() {
    return {
      upToken: "",
      content:""
    };
  },

  created() {
      getUploadToken().then(res => {
        //获取后台返回的七牛cdn uptoken
        this.upToken = res.data.uploadToken;
      });
  },
  methods: {
//这三个方法作为参数给七牛观察方法传递的,不能缺省

    //上传错误处理调用的(七牛返回的错误信息)
    next(res){
      //可以自己log下res,是上传的进度什么的;
    },
    error(err) {
      console.log(err); 
    },
     //成功处理后调用的方法
    complete(res) {
      //url拼接,返回markdown格式字符串,content是双向绑定数据,更进一步,你可以根据输入的光标位置决定markdown位置
      this.content += `![${res.name}](https://cdn.kagurakana.xyz/${res.name})`;
    },


    /**拖放监听处理chorme,其他未做适配 */
    imgDrop(e) {
//这里如果console.log(e)里面dataTransfer的files数组是空的,不用管
      let file = e.dataTransfer.files[0]; //获取拖放文件 Blob
      if (this.upToken) {

      //函数格式:qiniu.upload(file: blob, key: string, token: string, putExtra: object, config: object): observable

        let observable = qiniu.upload(
          file,
          file.name,
          this.upToken,
          { fname: file.name, params: {}, mimeType: null }, //putExtra
          { useCdnDomain: true } //config
        );

        //开始上传
        observable.subscribe(this.next,this.error,this.complete);
      }
    }
  }
};
</script>

<style lang='scss' scoped>
</style>

看一下效果:

JHCvDCqov7.gif

更进一步,你可以添加剪贴板上传图片而不是拖拽上传,或者根据光标位置插入markdown而不是在末尾插入.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容