Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
zaxlct opened this issue Oct 26, 2017 · 25 comments
Open

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

zaxlct opened this issue Oct 26, 2017 · 25 comments

Comments

@zaxlct
Copy link

zaxlct commented Oct 26, 2017

配合 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:https://otq0t8ph7.bkt.clouddn.com/' // 图片服务器的域名,展示时使用
const STATVIDEO = 'http:https://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:https://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>
@zaxlct
Copy link
Author

zaxlct commented Oct 26, 2017

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

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

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

@surmon-china
Copy link
Owner

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

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

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

@zaxlct
Copy link
Author

zaxlct commented Oct 26, 2017

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

@zetianul
Copy link

zetianul commented Nov 2, 2017

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

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

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

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

@surmon-china
Copy link
Owner

surmon-china commented Nov 6, 2017

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

@surmon-china
Copy link
Owner

@surmon-china
Copy link
Owner

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

@slevin57
Copy link

slevin57 commented Dec 27, 2017

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

@surmon-china
Copy link
Owner

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

@slevin57
Copy link

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

@feijuncheng
Copy link

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

@world520ai
Copy link

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

@hu-qi
Copy link

hu-qi commented Apr 24, 2018

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

@TuChenH
Copy link

TuChenH commented Jun 4, 2018

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

@stayfool
Copy link

stayfool commented Jun 6, 2018

这段改一下,解决插入后光标在左边的问题, 这句可以控制光标 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
Copy link

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

@Shangyunliang
Copy link

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

@China256
Copy link

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

@Zhulingyan
Copy link

Zhulingyan commented Sep 17, 2018

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
Copy link

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

@Skura23
Copy link

Skura23 commented May 5, 2020

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

@zoulinxin
Copy link

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

@zoulinxin
Copy link

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

@shmmly
Copy link

shmmly commented Oct 26, 2021

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

@zuoyifeng
Copy link

@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
Projects
None yet
Development

No branches or pull requests