Skip to content

配合 element-ui 实现上传图片/视频到七牛 demo #102

Open
@kele59

Description

@kele59

配合 element-ui 实现上传图片/视频到七牛的方法
按照上面博客里的教程,亲测可以成功。

这个博客作者并不是我,非常感谢这个作者。
然后下面附上我自己根据这个博客实现的代码,添加了不少注释,去掉了统计字数逻辑。

<style lang="sass">
.quill-editor
  min-height: 500px

  .ql-container
    min-height: 500px

.ql-snow .ql-editor img
  max-width: 480px

.ql-editor .ql-video
  max-width: 480px
</style>

<template lang="pug">
.the_my_editor_container
  quill-editor(
    v-model="content" 
    ref="myQuillEditor" 
    :options="editorOption" 
  )

  //- 文件上传input 将它隐藏
  el-upload.upload-demo(
    :action="qnLocation" 
    :before-upload='beforeUpload' 
    :data="uploadData" 
    :on-success='upScuccess' 
    ref="upload" 
    style="display:none"
  )
    el-button#imgInput(
      size="small" 
      type="primary" 
      v-loading.fullscreen.lock="fullscreenLoading" 
      element-loading-text="插入中,请稍候"
    ) 点击上传

</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'
import Quill from 'quill'

const STATICDOMAIN = 'http://otq0t8ph7.bkt.clouddn.com/' // 图片服务器的域名,展示时使用
const STATVIDEO = 'http://otq0t8ph7.bkt.clouddn.com/'

@Component
export default class Editor extends Vue {
  content = '' // 文章内容
  editorOption = {
    placeholder: '请输入内容',
  }
  addRange = []
  uploadData = {}
  photoUrl = '' // 上传图片地址
  uploadType = '' // 上传的文件类型(图片、视频)
  fullscreenLoading = false

  $refs = {
    myQuillEditor: HTMLInputElement,
    imgInput: HTMLInputElement
  }

  // 上传七牛的actiond地址,http 和 https �不一样
  get qnLocation() {
    return location.protocol === 'http:' ? 'http://upload.qiniu.com' : 'https://up.qbox.me'
  }

  // 图片上传之前调取的函数
  // 这个钩子还支持 promise
  beforeUpload(file) {
    return this.qnUpload(file)
  }

  // 图片上传前获得数据token数据
  qnUpload(file) {
    this.fullscreenLoading = true
    const suffix = file.name.split('.')
    const ext = suffix.splice(suffix.length - 1, 1)[0]
    console.log(this.uploadType)
    if (this.uploadType === 'image') { // 如果是点击插入图片
      // TODO 图片格式/大小限制
      return this.$http('common/get_qiniu_token').then(res => {
        this.uploadData = {
          key: `image/${suffix.join('.')}_${new Date().getTime()}.${ext}`,
          token: res.data
        }
      })
    } else if (this.uploadType === 'video') { // 如果是点击插入视频
      return this.$http('common/get_qiniu_token').then(res => {
        this.uploadData = {
          key: `video/${suffix.join('.')}_${new Date().getTime()}.${ext}`,
          token: res
        }
      })
    }
  }

  // 图片上传成功回调   插入到编辑器中
  upScuccess(e, file, fileList) {
    console.log(e)
    this.fullscreenLoading = false
    let vm = this
    let url = ''
    if (this.uploadType === 'image') { // 获得文件上传后的URL地址
      url = STATICDOMAIN + e.key
    } else if (this.uploadType === 'video') {
      url = STATVIDEO + e.key
    }
    if (url != null && url.length > 0) { // 将文件上传后的URL地址插入到编辑器文本中
      let value = url
      // API: https://segmentfault.com/q/1010000008951906
      // this.$refs.myTextEditor.quillEditor.getSelection();
      // 获取光标位置对象,里面有两个属性,一个是index 还有 一个length,这里要用range.index,即当前光标之前的内容长度,然后再利用 insertEmbed(length, 'image', imageUrl),插入图片即可。
      vm.addRange = vm.$refs.myQuillEditor.quill.getSelection()
      value = value.indexOf('http') !== -1 ? value : 'http:' + value
      vm.$refs.myQuillEditor.quill.insertEmbed(vm.addRange !== null ? vm.addRange.index : 0, vm.uploadType, value, Quill.sources.USER) // 调用编辑器的 insertEmbed 方法,插入URL
    } else {
      this.$message.error(`${vm.uploadType}插入失败`)
    }
    this.$refs['upload'].clearFiles() // 插入成功后清除input的内容
  }

  // 点击图片ICON触发事件
  imgHandler(state) {
    this.addRange = this.$refs.myQuillEditor.quill.getSelection()
    if (state) {
      let fileInput = document.getElementById('imgInput')
      fileInput.click() // 加一个触发事件
    }
    this.uploadType = 'image'
  }

  // 点击视频ICON触发事件
  videoHandler(state) {
    this.addRange = this.$refs.myQuillEditor.quill.getSelection()
    if (state) {
      let fileInput = document.getElementById('imgInput')
      fileInput.click() // 加一个触发事件
    }
    this.uploadType = 'video'
  }

  // 页面加载后执行 为编辑器的图片图标和视频图标绑定点击事件
  mounted() {
    // 为图片ICON绑定事件  getModule 为编辑器的内部属性
    this.$refs.myQuillEditor.quill.getModule('toolbar').addHandler('image', this.imgHandler)
    this.$refs.myQuillEditor.quill.getModule('toolbar').addHandler('video', this.videoHandler) // 为视频ICON绑定事件
  }
}
</script>

Activity

kele59

kele59 commented on Oct 26, 2017

@kele59
Author

改一下 STATICDOMAIN 变量,换成你自己的七牛配置的域名,
浏览器输入 STATICDOMAIN + key 就能访问你上传成功的图片/视频

这个只是客户端代码,还需要服务器实现一个接口,通过这个接口能获取七牛的 token 。
this.$http('common/get_qiniu_token') 这个方法换成你自己的获取token方法。

改完以上两点,亲测没问题。

surmon-china

surmon-china commented on Oct 26, 2017

@surmon-china
Owner

@zaxlct 仔细看了,跳到了简书原作者,写的很清晰,其实主要用到两个东西:

  1. 加一个按钮用于触发上传,可以用 html slotquill.getModule("toolbar").addHandler 控制
  2. 需要向编辑器插入内容时,使用getSelectioninsertEmbed插入内容

如果你的使用体验还不错,我觉得可以封装为一个“插件/模块”,发布,开放给用户吊起上传和数据输出的接口即可

kele59

kele59 commented on Oct 26, 2017

@kele59
Author

@surmon-china 目前使用上没啥问题,上传图片也都稳定。能封装一个插件更好,非常支持啊!我觉得很多用户都需要这个功能吧,为了搞定这个我也花费了好几天。。233333.。。。

zetianul

zetianul commented on Nov 2, 2017

@zetianul

富文本编辑器上传图片这个问题困扰了我好多天,刚刚解决,也是用的

加一个按钮用于触发上传,可以用 html slot 或 quill.getModule("toolbar").addHandler 控制

需要向编辑器插入内容时,使用getSelection 和insertEmbed插入内容

往toolbar中塞了一个按钮,图标用fontawsome,基本可以做到以假乱真,只不过我上传图片是调用的七牛的js sdk,要开个issue给别人提供一个参考吗。

surmon-china

surmon-china commented on Nov 6, 2017

@surmon-china
Owner
const range = this.$refs.myTextEditor.quill.getSelection();
const imageUrl = qiniuUpload(image);
this.$refs.myTextEditor.quill.insertEmbed(range.index, 'image', imageUrl);
surmon-china

surmon-china commented on Nov 13, 2017

@surmon-china
Owner

@mingtail 自己试,自己找,@我也只是我帮你做这两件事,没什么标准答案。

slevin57

slevin57 commented on Dec 27, 2017

@slevin57

@surmon-china 我用原生的api配合编辑器实现了这个功能,想按你说的封装成一个『插件/模块』,当锻炼自己造福大众
不过之前没做过也没具体的头绪,就想试试,能给个教程链接之类的么,先谢了

surmon-china

surmon-china commented on Dec 27, 2017

@surmon-china
Owner

@Patricklea 核心就是将对应 SDK 封装在一个 quill module 里,然后加上图标、事件、配置项,具体可以参考 quill module 部分的文档或以 README.md 底部推荐的第三方插件作为参考。

slevin57

slevin57 commented on Dec 28, 2017

@slevin57

@surmon-china 好,谢谢,我试下先。

feijuncheng

feijuncheng commented on Mar 2, 2018

@feijuncheng

在imgHandler中直接通过原生获取button的id会有问题,最好是还通过ref获取dom然后处理

world520ai

world520ai commented on Mar 16, 2018

@world520ai

想请教一下,如果上传了图片,后面删除了这个图片,怎么删除服务器上对应的图片呢

hu-qi

hu-qi commented on Apr 24, 2018

@hu-qi

想请教一下您 视频上传的进度怎么显示

TuChenH

TuChenH commented on Jun 4, 2018

@TuChenH

想请教一下 我按照这个写的,但是碰到了一个问题,就是每次选择文件的时候,屏幕会自动变成loding状态,正常上传完成是没有问题,但是如果我在选择文件的时候直接不选了,关掉选择文件框就会出现屏幕一直锁定在loading状态 无法点选其他, 请问这个怎么解决呢?

stayfool

stayfool commented on Jun 6, 2018

@stayfool

这段改一下,解决插入后光标在左边的问题, 这句可以控制光标 quill.setSelection(index + 1, 0)
image

          let selection =quill.getSelection()
          let value = url.indexOf('http') != -1 ? url : 'http:' + url
          let index = selection != null ? selection.index : 0
          quill.insertEmbed(index, 'image', value, Quill.sources.USER)
          quill.setSelection(index + 1, 0)
China256

China256 commented on Aug 14, 2018

@China256

@grubin1989 文件传上去名字一般都是唯一的md5编码。上传图片后找个地方保存他的文件名,然后和内容一起提交到服务器取出内容中的文件做比较。不存在的就删光光。:)

Shangyunliang

Shangyunliang commented on Aug 14, 2018

@Shangyunliang

这样上传的图片好像没有办法拖动进行排版. 有谁解决了这个问题吗

China256

China256 commented on Aug 14, 2018

@China256

@Shangyunliang 注意官方第四个demo,需要一个模块

keaiYan01

keaiYan01 commented on Sep 17, 2018

@keaiYan01

Invalid prop: type check failed for prop "data". Expected Object, got String.
Error in mounted hook: "TypeError: Cannot read property 'quill' of undefined"
请教一下,我按照您这个写出现这两个报错是为什么啊

BH-NOTHING

BH-NOTHING commented on May 13, 2019

@BH-NOTHING

建了个QQ群(770265969),大家可以进来一起讨论下vue-quill-editor

Skura23

Skura23 commented on May 5, 2020

@Skura23

上传到自己服务器: https://blog.csdn.net/lyj2018gyq/article/details/82585194
这个算是我找到最方便的了, 很多文章写的罗里吧嗦, 这个拿来用就行

zoulinxin

zoulinxin commented on May 27, 2020

@zoulinxin

想这种富文本中的文件保存到服务器上之后如果要删掉是怎么删除,这边是不是就删除不了了

zoulinxin

zoulinxin commented on May 27, 2020

@zoulinxin

这种富文本图片啥的上传之后,保存到服务器然后删除的话后端接口和前端需要怎么写呢

shmmly

shmmly commented on Oct 26, 2021

@shmmly

@zoulinxin 这种情况 感觉可以维护一个图库,将所有通过上传接口上传的图片统一维护起来,这样也可以避免已经上传的图片再次上传,同时也可以对已上传图片做一个分组,增删改查等基础功能。

zuoyifeng

zuoyifeng commented on Aug 29, 2023

@zuoyifeng

@surmon-china 大佬
vue上传视频后,v-model回显数据会把html中的
<video src="https://www.rtcxxx.com">标签的src地址转换成[object Object],导致视频无法回显显示播放,请问有办法解决了吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @world520ai@stayfool@China256@surmon-china@kele59

        Issue actions

          配合 element-ui 实现上传图片/视频到七牛 demo · Issue #102 · surmon-china/vue-quill-editor