TinyEditor 篇2:剪贴板粘贴图片并同步上传至服务器

书接上回,我们实现了富文本编辑器的工具栏图片上传按钮选择图片后,可以将图片上传至服务器,这一篇,来看看当我们复制了一张图片到剪贴板,粘贴到编辑器文本编辑区域时,如何同步上传至服务器呢?

功能实现

我们的实现步骤是:

当我们点击 Ctrl + V 的时候,FluentEditor 默认粘贴(插入 base64 图片),此处触发我们自己的粘贴处理方法 handlePaste,此时上传图片,调用FluentEditor 的 .insertEmbed 方法插入图片地址。这里直接上代码:

javascript 复制代码
<template>
  <div class="editor-container">
    <div ref="editorRef" class="editor-inside"></div>
  </div>
</template>
 
<script setup>
import { onMounted, ref } from 'vue'
import '@opentiny/fluent-editor/style.css'
import FluentEditor from '@opentiny/fluent-editor'
import axios from 'axios'
import { uploadFile } from '@/model/editor.js' // 这里使用自己的上传接口即可
 
const editorRef = ref(null)
let editorInstance = null
 
const TOOLBAR_CONFIG = [
  [{ header: [] }],
  ['bold', 'italic', 'underline', 'link'],
  [{ list: 'ordered' }, { list: 'bullet' }],
  ['clean'],
  ['image']
]
 
const selectImage = () => {
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = 'image/*'
  input.click()
 
  input.onchange = async () => {
    const file = input.files[0]
    if (!file) return
 
    try {
      const url = await uploadImage(file)
 
      const range = editorInstance.getSelection()
      editorInstance.insertEmbed(range.index, 'image', url)
 
    } catch (err) {
      console.error('上传失败', err)
    }
  }
}
 
const uploadImage = async (file) => {
  const ext = file.name.split('.').pop()
 
  const res = await uploadFile({ ext })
 
  const resData = res.data
  const uploadUrl = resData.upload_url
  const fileUrl = resData.public_url
 
  await axios.put(uploadUrl, file, {
    headers: {
      'Content-Type': file.type
    }
  })
 
  return fileUrl
}

const handlePaste = async (e) => {
  const items = e.clipboardData?.items
  if (!items) return

  for (let i = 0; i < items.length; i++) {
    const item = items[i]

    if (item.type.indexOf('image') !== -1) {
      e.preventDefault()
      e.stopPropagation()

      const file = item.getAsFile()

      try {
        const url = await uploadImage(file)

        const range = editorInstance.getSelection(true)
        editorInstance.insertEmbed(range.index, 'image', url)
      } catch (err) {
        console.error('粘贴上传失败', err)
      }

      break
    }
  }
}
 
onMounted(() => {
  if (!editorRef.value) return
 
  editorInstance = new FluentEditor(editorRef.value, {
    theme: 'snow',
    modules: {
      toolbar: {
        container: TOOLBAR_CONFIG,
        handlers: {
          image: selectImage
        }
      }
    }
  })

  editorRef.value.addEventListener('paste', handlePaste, true)
})
</script>
 
<style scoped>
.editor-container {
  width: 50%;
  display: flex;
  justify-content: center;
  padding-top: 20px;
}
 
.editor-inside {
  height: 350px;
}
 
.editor-inside :deep(.ql-container) {
  height: 350px;
}
 
.editor-inside :deep(.ql-editor) {
  height: 310px;
}
</style>

注意:我们在监听 paste 的时候,第三个入参传了 true,是为了阻止编辑器默认的图片粘贴行为,如果不写,那么我们在粘贴图片的时候,会粘贴进去两张图片。

下一篇,我们看看将图片拖拽到编辑器中如何渲染和上传。

相关推荐
狗都不学爬虫_11 小时前
小程序逆向 - Hai尔(AliV3拖动物品)
javascript·爬虫·python·网络爬虫
We་ct11 小时前
HTML5 原生拖拽 API 基础原理与核心机制
前端·javascript·html·api·html5·浏览器·拖拽
YIN_尹11 小时前
【Linux系统编程】进程控制(一)
linux·运维·服务器
是上好佳佳佳呀11 小时前
【前端(八)】CSS3 属性值笔记:渐变、自定义字体与字体图标
前端·笔记·css3
踩着两条虫11 小时前
VTJ:核心引擎
前端·低代码·ai编程
被摘下的星星11 小时前
网络设备有哪些
服务器·网络
aini_lovee11 小时前
基于C#的三菱PLC串口通信实现方案
服务器·网络·c#
.柒宇.11 小时前
共享文件服务NFS服务器:NFS实战详解
linux·运维·服务器
GISer_Jing12 小时前
AI时代前端开发者成长计划
前端·人工智能
一叶之秋141212 小时前
通信之道:解锁Linux进程间通信的无限可能(三)
linux·运维·服务器