将文件数据流式传输到mongodb gridfs中

时间:2014-06-17 18:27:42

标签: python python-2.7 mongoengine gridfs

我尝试在服务器上使用django + mongoengine将视频文件上传到gridfs。

客户端: JavaScript读取/分块文件并使用ajax将数据发送到服务器。

_upload : function() {
    chunk = self.file.slice( self.start, self.end );
    reader = new FileReader();
    reader.readAsDataURL( chunk );
    reader.onload = function(e) {
        this.request = new XMLHttpRequest();
        this.request.open( 'POST', '/ajax/video_upload/' );
        this.request.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        this.request.overrideMimeType('application/octet-stream');
        this.request.send( JSON.stringify({ 'chunk': e.target.result, 'id' : self.file_id }) );
        this.request.onload = function() {

        if( self.start >= self.file_size && self.preventedOverflow ) {
        return;
        }

        self.start = self.end;
        self.end = self.end + self.chunkSize;

       self._upload();
    };
}

服务器端:

def uploadVideo(request):
if request.body and request.is_ajax:
    data = json.loads(request.body)
    m = Multimedia.objects.get( id = data['id'] )
    m.media.new_file()
    m.media.write( data['chunk'] )
    m.media.close()
    m.save()
    return HttpResponse()

错误:

ERROR:django.request:Internal Server Error: /ajax/video_upload/
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 115, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/home/praveen/Desktop/gatherify/gatherify/../ajax/views.py", line 33, in uploadVideo
    m.media.write( data['chunk'] )
  File "/usr/local/lib/python2.7/dist-packages/mongoengine-0.8.7-py2.7.egg/mongoengine/fields.py", line 1172, in write
    self.newfile.write(string)
  File "build/bdist.linux-i686/egg/gridfs/grid_file.py", line 327, in write
    "order to write %s" % (text_type.__name__,))
TypeError: must specify an encoding for file in order to write unicode

我不知道如何指定官方文档没有说明的编码。 (http://mongoengine-odm.readthedocs.org/guide/gridfs.html

另一个问题是,当我尝试在下一个ajax请求中编写下一个块时,我收到一个错误:

GridFSError: This document already has a file. Either delete it or call replace to overwrite it

感谢任何帮助。谢谢:))

2 个答案:

答案 0 :(得分:2)

在将data['chunk']字符串写入FileField之前对其进行编码。

m.media.new_file()
m.media.write( data['chunk'].encode("UTF-8") )
m.media.close()

至于你的第二个问题,你已经在gridfs中创建了一个文件。如错误消息所示,您必须m.media.delete()m.media.replace(<a new gridfs entry>)它。如果你想要附加它,你可能需要将m.media.get()文件内容作为字符串,将新块附加到字符串,然后创建一个新的m.media gridfs文件。您无法直接编辑gridfs内容。

答案 1 :(得分:0)

  1. 您需要以utf-8
  2. 编写数据
  3. 在您只编写第一个块后,您不应该关闭从newfile获取的GridOut实例
  4. 您应该为每个新文件上传创建一个greenlet
  5. 写完大块后的收益
  6. 发送ack接收下一个块也有一些&#39; id&#39;识别greenlet。
  7. 唤醒greenlet并发送新块
  8. 发送&#39;文件结尾&#39;一旦没有留下任何块
  9. 现在关闭GridOut。
  10. 退出greenlet