wangEditor 5上传图片到七牛云

398 阅读2分钟

相关视频地址:www.bilibili.com/video/BV1ct…

在wangEditor中把图片上传到七牛云保存,以NextJS框架为例进行展示。

wangEditor​www.wangeditor.com/

安装基本的依赖包

npm i @wangeditor/editor @wangeditor/editor-for-react qiniu qiniu-js uuid

在环境变量中写入七牛配置

// 七牛空间名
QINIU_BUCKET = XXXXXXXXXX
// 七牛云的 AK 和 SK
QINIU_AK = XXXXXXXXXXXXXXXXXX
QINIU_SK = XXXXXXXXXXXXXXXXXXX
// 七牛云的 CDN 地址
NEXT_PUBLIC_CDN = XXXXXXXXXXXXXXXX

在前端创建wangEditor组件

'use client';

import '@wangeditor/editor/dist/css/style.css'; // 引入 css

import React, { useState, useEffect } from 'react';
import { Editor, Toolbar } from '@wangeditor/editor-for-react';
import { IDomEditor, IEditorConfig, IToolbarConfig } from '@wangeditor/editor';
import { v4 as uuidv4 } from 'uuid';
import * as qiniu from 'qiniu-js'

type InsertFnType = (url: string, alt: string, href: string) => void

function MyEditor({ html, setHtml }: { html: string; setHtml: any }) {
  // editor 实例
  const [editor, setEditor] = useState<IDomEditor | null>(null); // TS 语法
  // const [editor, setEditor] = useState(null)                   // JS 语法

  // 模拟 ajax 请求,异步设置 html
  useEffect(() => {
    // setTimeout(() => {
    //   setHtml('<p>hello world</p>');
    // }, 1500);
  }, []);

  // 获取七牛云上传 token
  const getToken = async (key: string) => {
    const res = await fetch(`/api/admin/upload/token?key=${key}`);
    const data = await res.json();
    return data.token;
  }

  // cdn
  const cnd = process.env.NEXT_PUBLIC_CDN;

  // 工具栏配置
  const toolbarConfig: Partial<IToolbarConfig> = {}; // TS 语法
  // const toolbarConfig = { }                        // JS 语法

  // 编辑器配置
  const editorConfig: Partial<IEditorConfig> = {
    // TS 语法
    // const editorConfig = {                         // JS 语法
    placeholder: '请输入内容...',
    MENU_CONF: {
      uploadImage: {
        async customUpload(file: File, insertFn: InsertFnType) {  // TS 语法
          // 获得文件名
          const key = uuidv4();
          const token = await getToken(key)
          // 上传文件
          const observable = qiniu.upload(file, key, token)
          observable.subscribe({
            next: (res) => {
              // 进度展示
              console.log(res, '进度')
            }, 
            error: (err) => {
              console.log(err, '错误')
            },
            complete: (res) => {
              console.log(res, '完成')
              const url = cnd + res.key
              insertFn(url, file.name, res.key)
            }
          })
        }
      },
    },
  };

  // 销毁editor
  useEffect(() => {
    return () => {
      if (editor == null) return;
      editor.destroy();
      setEditor(null);
    };
  }, [editor]);

  return (
    <>
      <div style={{ border: '1px solid #ccc', zIndex: 100 }}>
        <Toolbar
          editor={editor}
          defaultConfig={toolbarConfig}
          mode='default'
          style={{ borderBottom: '1px solid #ccc' }}
        />
        <Editor
          defaultConfig={editorConfig}
          value={html}
          onCreated={setEditor}
          onChange={(editor) => setHtml(editor.getHtml())}
          mode='default'
          style={{ height: '500px', overflowY: 'hidden' }}
        />
      </div>
      {/* <div style={{ marginTop: '15px' }}>{html}</div> */}
    </>
  );
}

export default MyEditor;

具体解释:

1、使用wangEditor的customUpload功能,在customUpload里面,生成上传图片的key,然后通过服务端接口获取七牛的token。

// 获取七牛云上传 token
  const getToken = async (key: string) => {
    const res = await fetch(服务端接口地址);
    const data = await res.json();
    return data.token;
  }

2、服务端生成token

import qiniu from 'qiniu';
import { NextRequest, NextResponse } from 'next/server';

export const GET = async (req: NextRequest) => {
  // 获取key
  const key = req.nextUrl.searchParams.get('key');
  // 环境变量读取七牛配置
  const bucket = process.env.QINIU_BUCKET;
  const accessKey = process.env.QINIU_AK;
  const secretKey = process.env.QINIU_SK;

  // 创建鉴权对象
  const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
  const options = {
    scope: bucket + ':' + key,
    expires: 7200
  };
  const putPolicy = new qiniu.rs.PutPolicy(options);
  const uploadToken=putPolicy.uploadToken(mac);
  // 返回token
  return NextResponse.json({
    token: uploadToken,
  });
}

七牛官方文档:developer.qiniu.com/kodo/1289/n…

3、使用七牛客户端工具上传

const observable = qiniu.upload(file, key, token)
          observable.subscribe({
            next: (res) => {
              // 进度展示
              console.log(res, '进度')
            }, 
            error: (err) => {
              console.log(err, '错误')
            },
            complete: (res) => {
              console.log(res, '完成')
              const url = cnd + res.key
              insertFn(url, file.name, res.key)
            }
          })

七牛官方文档:JavaScript SDK_SDK 下载_对象存储 - 七牛开发者中心

wangEditor文档:菜单配置 | wangEditor

最后,在客户端页面中可以直接使用当前的组件。