Flask项目集成富文本编辑器XHEditor

标签: flask xheditor 富文本编辑器 | 发表时间:2014-12-23 09:28 | 作者:digwtx
出处:http://segmentfault.com/blogs

本文介绍如何在Flask项目中集成富文本编辑器xhEditor,并实现图片上传、文件上传、视频上传、远程抓图等(包括拖拽上传)功能。

xhEditor简介

xhEditor是一个基于jQuery开发的简单迷你并且高效的可视化HTML编辑器,基于网络访问并且兼容IE 6.0+, Firefox 3.0+, Opera 9.6+, Chrome 1.0+, Safari 3.22+。

xhEditor曾经是我比较喜欢的编辑器,也是率先支持拖拽上传的编辑器之一。xhEditor在当年是优秀的编辑器,功能足够强大,使用体验也相当好,拖拽上传是我最喜欢的功能,只可惜已经停止开发了。xhEditor最后的稳定版本是1.1.14,至今已超过2年未更新(2013年发布了开发版本1.2.1),作者已经停止开发和维护了,社区论坛完全不能打开。

由于xhEditor基于jQuery开发,而对于新版本的jQuery,它并不能很好的支持,只有1.4版本的jQuery是支持得最好的。

虽然已经不再更新了,但在一些需要富文本编辑器的场合,她还是可以完全胜任的。

本文以1.1.14版本为例,讲述如何在Flask项目中使用xhEditor编辑器,并实现图片上传、文件上传的后端功能。

在Flask项目中使用xhEditor

首先我们需要到 xhEditor官网下载1.1.14版本的xhEditor编辑器,下载之后解压到
Flask项目的 static/xheditor目录。

xhEditor下载

xhEditor文件结构

xhEditor提供2种初始化方式:Class初始化和JavaScript初始化。Class初始化只需要给textarea设置值为 xheditorclass属性,它就会自动变成xhEditor编辑器,一个页面可以同时同在多个编辑器,而且这个类属性可以添加参数。(PS:CKEditor也有这个功能)

对于这两种初始化方式,官网有提供设置很方便的设置向导,使得配置相对比较简单。

示例代码:

  html  <head>
<script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='xheditor/jquery/jquery-1.4.4.min.js') }}"></script>
<script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='xheditor/xheditor-1.1.14-zh-cn.min.js') }}"></script>
<style>.xheditor {width: 640px; height:320px;}</style>
</head>

<body>
<textarea id="content" name="content" class="xheditor {tools:'mfull'}"></textarea>
</body>

现在,我们就拥有一个xhEditor编辑器了。

xhEditor编辑器

开启上传功能

xhEditor的上传功能需要设置几个参数(以图片上传为例):

  • upImgUrl : 图片文件上传接收URL,例: /upload/,可使用内置变量 {editorRoot}
  • upImgExt : 图片上传前限制本地文件扩展名,默认:jpg,jpeg,gif,png

这里假设上传文件接收URL为 /upload/,我们的编辑器初始化代码就变成:

  html  <textarea class="xheditor {tools:'mfull',upImgUrl:'/upload/'}"></textarea>

其他类型的文件上传设置类推。

Flask处理上传请求

xhEditor支持2种上传方式:标准HTML4上传和HTML5上传。

  1. HTML4上传使用标准的表单上传域,上传文件域的name为: filedata
  2. HTML5上传的整个POST数据流就是上传的文件完整数据,而本地文件名等信息储
    存于 HTTP_CONTENT_DISPOSITION这个服务器变量中

返回内容必需是标准的json字符串,结构可以是如下:
{"err":"","msg":"200906030521128703.gif"} 或者
{"err":"","msg":{"url":"200906030521128703.jpg","localfile":"test.jpg","id":"1"}}

注:若选择结构2,则 url变量是必有。

文件上传处理示例代码:

  python  def gen_rnd_filename():
    filename_prefix = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    return '%s%s' % (filename_prefix, str(random.randrange(1000, 10000)))

@app.route('/upload/', methods=['GET', 'POST'])
def upload():
    '''文件上传函数

    本函数未做上传类型判断及上传大小判断。
    '''
    result = {"err": "", "msg": {"url": "", "localfile": ""}}

    if request.method == 'POST' and 'filedata' in request.files:
        # 传统上传模式,IE浏览器使用这种模式
        fileobj = request.files['filedata']
        fname, fext = os.path.splitext(fileobj.filename)
        rnd_name = '%s%s' % (gen_rnd_filename(), fext)
        fileobj.save(os.path.join(app.static_folder, 'upload', rnd_name))
        result["msg"]["localfile"] = fileobj.filename
        result["msg"]["url"] = '!%s' % \
            url_for('static', filename='%s/%s' % ('upload', rnd_name))

    elif 'CONTENT_DISPOSITION' in request.headers:
        # HTML5上传模式,FIREFOX等默认使用此模式
        pattern = re.compile(r"""\s.*?\s?filename\s*=\s*['|"]?([^\s'"]+).*?""", re.I)
        _d = request.headers.get('CONTENT_DISPOSITION').encode('utf-8')
        if urllib.quote(_d).count('%25') > 0:
            _d = urllib.unquote(_d)
        filenames = pattern.findall(_d)
        if len(filenames) == 1:
            result["msg"]["localfile"] = urllib.unquote(filenames[0])
            fname, fext = os.path.splitext(filenames[0])
        img = request.data
        rnd_name = '%s%s' % (gen_rnd_filename(), fext)
        with open(os.path.join(app.static_folder, 'upload', rnd_name), 'wb') as fp:
            fp.write(img)

        result["msg"]["url"] = '!%s' % \
            url_for('static', filename='%s/%s' % ('upload', rnd_name))

    return json.dumps(result)

远程抓图

一般情况下,当复制站外的图片时,我们希望可以把图片保存到本地,远程抓图就可以完成这个事情。

启用远程抓图功能,需要设置2个参数:

  • localUrlTest : 非本站域名测试正则表达式
  • remoteImgSaveUrl : 远程图片抓取接收程序URL

设置这2个参数之后,我们的编辑器初始化代码变成:

  html  <textarea class="xheditor {tools:'mfull',upImgUrl:'/upload/',localUrlTest:/^https?:\/\/[^\/]*?(localhost:?\d*)\//i,remoteImgSaveUrl:'/uploadremote/'}"></textarea>

这里表示抓取除 localhost之外其它域名的图片。

远程抓图处理示例代码:

  python  def gen_rnd_filename():
    filename_prefix = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    return '%s%s' % (filename_prefix, str(random.randrange(1000, 10000)))

@app.route('/uploadremote/', methods=['POST'])
def uploadremote():
    """
    xheditor保存远程图片简单实现
    URL用"|"分隔,返回的字符串也是用"|"分隔
    返回格式是字符串,不是JSON格式
    """
    localdomain_re = re.compile(r'https?:\/\/[^\/]*?(localhost:?\d*)\/', re.I)
    imageTypes = {'gif': '.gif', 'jpeg': '.jpg', 'jpg': '.jpg', 'png': '.png'}
    urlout = []
    result = ''
    srcUrl = request.form.get('urls')
    if srcUrl:
        urls = srcUrl.split('|')
        for url in urls:
            if not localdomain_re.search(url.strip()):
                downfile = urllib.urlopen(url)
                fext = imageTypes[downfile.headers.getsubtype().lower()]
                rnd_name = '%s%s' % (gen_rnd_filename(), fext)
                with open(os.path.join(app.static_folder, 'upload', rnd_name), 'wb') as fp:
                    fp.write(downfile.read())
                urlreturn = url_for('static', filename='%s/%s' % ('upload', rnd_name))
                urlout.append(urlreturn)
            else:
                urlout.append(url)
    result = '|'.join(urlout)
    return result

完整DEMO

这里有个简单的DEMO: https://coding.net/wtx358/flask-xheditor-demo.git

小结

虽然xhEditor已经不再更新了,但仍不失为一款优秀的富文本编辑器,它的文件上传方式也值得借鉴。不过呢,项目中更多地会选择CKEditor或者UEditor这类比较活跃的编辑器。

原文: http://flask123.sinaapp.com/article/51/

相关 [flask 项目 富文本] 推荐:

Flask项目集成富文本编辑器XHEditor

- - SegmentFault 最新的文章
本文介绍如何在Flask项目中集成富文本编辑器xhEditor,并实现图片上传、文件上传、视频上传、远程抓图等(包括拖拽上传)功能. xhEditor是一个基于jQuery开发的简单迷你并且高效的可视化HTML编辑器,基于网络访问并且兼容IE 6.0+, Firefox 3.0+, Opera 9.6+, Chrome 1.0+, Safari 3.22+.

Flask-Babel 简介

- yinseny - python.cn(jobs, news)
本文有一个格式好看一点,并且有语法高亮的版本放在 readthedocs,欢迎浏览. 本文是原创,不是翻译,不过本文其实是谈翻译的. 话说用 wordpress 的 WYSIWYG 编辑器写这样的文章真痛苦啊,格式一不小心就乱了,本文是用 rst 写成,编译为 html,然后贴到这边来的. 最近用 Flask 给公司做了个小 web 应用,做的时候用英文了,现在要求翻译成中文.

Flask + Gunicorn + Nginx 部署 - Ray Liang

- - 博客园_首页
最近很多朋友都在问我关于 Flask 部署的问题,说实在的我很乐意看到和回答这样的问题,至少证明了越来越多人开始用 Flask 了. 之前我曾发表过一篇在 Ubuntu 上用 uwsgi + nginx 的 Flask 部署方法,说实在的 uwsgi 是个大坑可能用在 Django 上还好吧,不过用在 Flask 上未必就如此.

使用 Flask 搭建静态博客

- - vpsee.com
现在流行的静态博客/网站生成工具有很多,比如 Jekyll, Pelican, Middleman, Hyde 等等, StaticGen 列出了目前最流行的一些静态网站生成工具. 我们的内部工具由 Python/Flask/MongoDB 搭建,现在需要加上文档功能,写作格式是 Markdown,不想把文档放到数据库里,也不想再弄一套静态博客工具来管理文档,于是找到了 Flask-FlatPages 这个好用的 Flask 模块.

Flask, Tornado, GEvent, 以及它们的结合的性能比较

- Ken - python.cn(jobs, news)
英文: http://blog.wensheng.com/2011/10/performance-of-flask-tornado-gevent-and.html. 我在选一个python的互联网框架, 本来已经定下来用Tornado了.  但我还听到很多人推荐Flask的简单性和灵活性, 还有gevent的高性能, 所以决定也试试它们以及它们和Tornado的结合.

使用React和Flask开发一个留言板

- - SegmentFault 最新的文章
近期要在生产环境上使用react,所以,自己学习了一下,写了一个简单的留言板小程序. 完整的代码可以到这里下载: message-board. 前端使用React,然后还有Bootstrap和jQuery,React负责前端展现,jQuery主要是向服务器发送ajax请求. 后端使用Flask和MongoDB,为前端提供数据.

通过 Flask, Docker, Jenkins 和 Kubernets 部署机器学习模型

- - 吴良超的学习笔记
本文主要介绍部署机器学习模型的一种自动化方式,如题所示,通过 Flask, Docker, Jenkins 和 Kubernets 实现. 基本原理就是通过 Fflask 提供暴露出 RESTful API 接收客户端的 predict 请求,然后将这个服务打包成一个 docker image 便于部署和迁移,当代码或模型更新时通过 Jenkins 触发自动构建新的 docker image,而通过 kubernets 管理容器则让整个服务具备伸缩性和可靠性.

[分享创造] 一个使用 Flask+gorse 实现的 Steam 游戏推荐系统

- - V2EX
之前小弟在 V2EX 推广过 一个 Go 语言实现的 RESTful 的推荐系统后端,最近以它为后端,使用 Flask 实现了一个 Steam 推荐系统,发在 V2EX 听取一下老哥们的意见. 关于工程量:因为 gorse 完成了大部分的逻辑,所以 Python 代码也就一百多行. 前端用的是 Materialize,后端用的是 Flask.

富文本编辑器杂谈

- - 标点符
在开发内容型网站的时候,少不了要接触富文本编辑器. 对开发人员来说,全新开发一个富文本编辑器会耗费大量的时间在细节的调整和坑的处理上. 在针对内部用户使用的系统中,普遍采用的方式是接入现成的开源编辑器,做简单的功能配置. 而针对面向普通用户的系统,富文本编辑器往往是单独进行设计和开发的. 在把一些功能较多,且可以配置功能项的编辑器称为传统编辑器,这类编辑器是最早出现的我们身边的,典型的代表有:百度的 ueditor、 ckeditor 4和 tinymce.

Essay:脱颖而出的富文本编辑器

- Jarod - 爱范儿 · Beats of Bits
iPhone 上的文字处理软件非常多,为什么要推荐这款 Essay. 因为它的简洁高效,因为它的云端同步,因为它顺手的控制功能,Essay 完全有实力成为沙砾中的宝石. 在 iPhone 上处理纯文本,用自带的备忘录就足够了,在什么情况下需要处理富文本呢. 例如想用 iPhone 完成一篇博客. 你当然可以用 WordPress for iPhone ,但它粗糙的功能和简陋的编辑器会让你失去愉快的感觉.