

为Open edX集成七牛云存储
source link: http://wwj718.github.io/post/edx/open-edx-qiniu/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Open edX与视频流
在Open edX的众多组件和服务中,并不包含视频流服务。不可否认的是,在线教育中,视频是要素之一,也许是最重要的要素之一,对一些人而言,甚至没有之一。
视频流一般被视为一个common server,市面上有数不清的商业或是开源解决方案,Open edX没有去重造车轮,而是和youtube做了很多整合。我们与youtube无缘。当然作为通用的组件,Open edX中的视频模块支持一般的视频资源(url),无论是云存储还是自建服务
自建视频流
如果准备自建视频流服务,可以参考@MT的在内部网络为edX配置视频服务。对于局域网内的用户(学校/企业),自建服务是个有诱惑力的方案。
不过这里边存在的坑是,视频流服务搭建不难,搭建一个友好的客户端,上传管理视频却颇为不易。在此推荐使用minio作为管理视频资源的工具,细节可以参考我的这篇文章:构建类s3存储系统(Minio)
使用云存储
视频解决方案有很多,大家可以自行google,看大家的对比评测,再结合自己的需求选型,在此就不多推荐了
我比较偏好七牛云。对开发者友好,api写得很漂亮
在此演示如何使用七牛云为open edX提供视频服务,并将客户端(js)集成其中
思路与设计
首先我们需要考虑一个问题,视频管理入口以什么形态集成到Open edX中合适(如何集成七牛云存储)。换个角度,Open edX有哪些拓展方式呢。毕竟我们可以把集成外部存储系统,看做一次对系统的拓展
在Extending edX中,官方给出了集中常见的拓展方式。此外还有两种很典型的拓展:
- 对django开发者而言还可以直接侵入式拓展open edx,通过添加django app或者修改增强mvt中的任何一个环节
- 模仿insights的做法,完全构建一个新的服务(网站),之后使用oauth2来打通用户系统
因为我们希望将系统集成到open edx内部,所以决定采用添加django app的做法。 用户上传和管理视频资源需要UI界面,参考Adding a UI Page,发现侵入式地定制open edx很是繁琐,我们决定为此功能写一个独立的页面,绕开繁重的前端架构
为何不是xblock
也许许多Open edX用户会觉得为何放着xlock不用,而采用侵入性更大的django app来拓展呢。原因有二:
- 视频管理是一个用户视角下,全局性的操作,应该有一个同意的资源管理入口,而不是每次需要先添加一个组件,再在组件里边管理视频,逻辑上,这样也能做出来。我们可以把xblock视为必须实例化(instance)为组件的东西
- 我们不想放弃既有的视频组件(数据采集等强大功能)
关于七牛云你需要了解的知识和上传管理的逻辑,可以参考我此前的文章:为Open edX构建存储服务
如果你想读懂接下来的源码,你需要了解django和django-restful-framework,如果只是用的话,就无所谓
just do it
我们直接在/edx/app/edxapp/edx-platform/cms/djangoapps
添加一个django appqiniu_storage
,形如:
├── add_the_app.sh
├── ajax.js
├── __init__.py
├── models.py
├── permissions.py
├── readme.md
├── serializers.py
├── urls.py
├── views.py
我们重点介绍model和view部分,其他不赘述
models.py
#!/usr/bin/env python
# encoding: utf-8
from __future__ import unicode_literals
from django.db import models
#from django.contrib.auth.models import User
class QiniuFiles(models.Model):
course_id = models.CharField(max_length=100,blank=True)
username = models.CharField(max_length=50,blank=True) # 上传用户,资源所有者
file_key = models.CharField(max_length=100)
file_url = models.CharField(max_length=100,blank=True)
file_name = models.CharField(max_length=100)
file_size = models.CharField(max_length=20,default="0")
#endUser = Column(String(100),nullable=True)
create_time = models.DateTimeField(u'创建时间',auto_now=True)
class Meta:
ordering = ('create_time',)
views.py
只列出关键部分
qiniu_access_key = getattr(settings, "QINIU_ACCESS_KEY", None)
class QiniuFilesViewSet(viewsets.ModelViewSet):
authentication_classes = (TokenAuthentication, SessionAuthentication,)
serializer_class = QiniuFilesSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)
def get_queryset(self):
"""
This view should return a list of all the purchases
for the currently authenticated user.
"""
return QiniuFiles.objects.filter(username=self.request.user.username) #用户级别的管理权限,每个用户只能管理自己上传的文件
# 删除功能暂不演示
其中的IsOwnerOrReadOnly
值得关注,校验用户与资源的关系
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.username == request.user.username
前端部分主要参考七牛的js-sdk,使用了clipboard.js用于点击事件,使用了noty用于消息提醒
代码形如:
$(function() {
var uploader = Qiniu.uploader({
runtimes: 'html5,flash,html4',
browse_button: 'pickfiles',//是哪个可上传的元素
container: 'container',
drop_element: 'container',//是否可拖动,且是哪个元素
max_file_size: '1000mb',
// flash_swf_url: 'bower_components/plupload/js/Moxie.swf',
dragdrop: true,
chunk_size: '4mb',
//uptoken: 'xxx' //测试用
uptoken_url: '/qiniu/uptoken', //key由后端生成,定制化的规则包含在载荷中
domain: 'xxx',//这是域名的绑定地址
get_new_uptoken: false,
unique_names: true,
auto_start: true,
log_level: 5,
...
上传流程涉及的代码
在七牛的上传原理中,上传需要凭证,我们来看看凭证的生成规则
@api_view(['GET'])
def make_uptoken(request, format=None):
test_uptoken = QiniuTool().get_test_uptoken(request)
#跨域的问题 Access-Control-Allow-Origin
response = Response({"uptoken": test_uptoken})
return response
其中Qiniu类为
class QiniuTool(object):
'''
#处理七牛凭证相关的工具,生成uptoken
存储相关的部分被抽象为rest服务
函数只接受get和post
'''
callback_url = 'http://studio.xxx.com/qiniu/post_from_qiniu'
#http://developer.qiniu.com/article/kodo/kodo-developer/up/vars.html 所有的魔法变量
#callback_body = 'filename=$(fname)&filesize=$(fsize)&key=$(key)&mimeType=$(mimeType)&endUser=$(endUser)&etag=$(etag)'
access_key = getattr(settings, "QINIU_ACCESS_KEY", None)
secret_key = getattr(settings, "QINIU_SECRET_KEY", None)
q = Auth(access_key, secret_key) # access_key和secret_key来自settings里
bucket_name = "easy-edx"
def get_test_uptoken(self,request):
callback_body = 'file_name=$(fname)&file_size=$(fsize)&file_key=$(key)&mimeType=$(mimeType)&endUser=$(endUser)&etag=$(etag)&username={}'.format(request.user.username)
# 上传策略有许多可选的参数,方便服务于业务逻辑:参考[python-sdk](http://developer.qiniu.com/docs/v6/sdk/python-sdk.html)
#上传文件到七牛后, 七牛将文件名和文件大小回调给业务服务器。
policy={
'scope':self.bucket_name,
'callbackUrl':self.callback_url, #回调 请求方式为POST
'callbackBody':callback_body
}
#token = q.upload_token(bucket_name,3600,policy)
token = self.q.upload_token(self.bucket_name,policy=policy)
return token
视频上传好之后,七牛会可以发送一个消息给服务器,我们在此存下文件信息即可
from qiniu_files.serializers import QiniuFilesSerializer
@api_view(['POST'])
def post_from_qiniu(request, format=None):
origin_authorization = request.META.get('HTTP_AUTHORIZATION', None)
access_key = re.split(r'\W',origin_authorization)[1]
request.data["file_url"] = "http://media.xxx.com/"+ request.data["file_key"]
request.data["file_size"] = request.data["file_size"]
serializer = QiniuFilesSerializer(data=request.data)
if access_key == Qiniu().access_key and serializer.is_valid():
serializer.save() #把信息存储到qiniu_storage模型里
instance = serializer.save()
data = file_info_format(request.data)
#使用序列化就能存入本地
data["id"]=instance.pk
return Response(data)
return Response({"success":False,"message":u"请求不合格"})
还有许多细节可以改进,诸如校验用户是否有教师权限
上边实际给出了open edx集成外部存储的方式,思路是通用的,不限于七牛。诸如你也可以将你自建的视频存储集成到open edx中,区别仅在抽象的存储接口(我们可以用minio构建)
Recommend
-
38
README.rst This is the source code for the edX mobile iOS app. It is changing rapidly and its structure should not be relied upon. See
-
8
批量下载七牛对象存储文件 分类:技术 | 12月 12th, 2018 | 1,801 views |
-
17
网址改用七牛云存储图片如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看...
-
8
七牛云对象存储地区对应表 - 搞搞震存储区域 地域简称 上传域名 华东 z0 服务器端上传:http(s)://up.qiniup.com 客户端上传: http(s)://upload.qiniup.com 华北 z1 服务器端上传:http(s)://up-z1.qiniup.com
-
8
Jager · 8月5日 · 2014年七牛云存储 · 备份到七牛 3203次已读上一篇文章...
-
7
Jager · 7月31日 · 2014年七牛云存储 · 网站备份 3457次已读一直想写一篇关于网站...
-
1
为Open edX构建存储服务 2016-02-28 edx ...
-
10
搭建远程会议系统(简单得集成到edx里) 2015-08-04
-
9
springboot项目上传存储图片到七牛云服务器 问题描述: 当图片存在本地时会出现卡顿的现象。比如一篇图文混排的文章,如果图片没有加载完,可能整个文章都显示不出来,因为它们都是用的同一个服务器...
-
6
近日心血来潮想做一个开源项目,目标是做一款可以适配多端、功能完备的模板工程,包含后台管理系统和前台系统,开发者基于此项目进行裁剪和扩展来完成自己的功能开发。本项目为前后端分离开发,后端基于Java21和SpringBoot3开发,后端使用...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK