Django频道文件/图片上传

cwi*_*irz 6 upload websocket django-channels

我想使用django-channels上传文件和图像,但我不知道从哪里开始。似乎没有太多关于 websockets 和文件/图像上传的文档。有任何想法吗?

kag*_*ick 2

执行此操作的唯一真正方法是使用通道 2,因为使用者在会话期间持续存在,并且您可以将文件对象作为实例变量放在其上。

您可以看到我如何使用文件字段并首先在其上发送一些初始化参数。我把重要的部分拿出来:

// Some class setup before this

// File field object
this.file = field.files[0];
init_params.action = 'prepare';
init_params.file_name = this.file.name;
init_params.file_size = this.file.size;

// This is a wrapper I have that gets a websocket. 
// The callback is called on connect. It sends the initialization parameters.
var ws = get_websocket(url, function(){
    this.send(JSON.stringify(init_params));
});

// After the initialization params are sent this is called with 0 as a parameter. 
// As the web server oks each chunk this is called with the next offset to send. chunk_size needs to be set somewhere.
var load_data = function(index) {
    var end =  index + this.chunk_size;
    if (index >= this.file.size)
        return;
    if (end > this.file.size)
        end = this.file.size;
    ws.send(this.file.slice(index, end));
}.bind(this);

ws.onmessage = function(msg) {
    var message = JSON.parse(msg.data);
    switch (message.action) {
        case 'progress':
            // This is called each time a chunk is written
            load_data(message.file_size);
            break;
        case 'ready':
            // This comes in to kick everything off
            load_data(0);
            break;
        case 'complete':
            // Handle complete
            break;
            }
        };
    }.bind(this);
Run Code Online (Sandbox Code Playgroud)

在消费者中,我们检查它是否是文本数据,如果是,我们将其作为 JSON 处理以设置文件。如果是二进制数据,我们像这样写出每个块。

    async def handle_json(self, message):
         self.session = {
             # Set up file object and attributes
         }

    async def handle_chunk(self, message, **kwargs):
        upload_size = self.session.get('upload_size')
        temp_destination = self.session.get('upload_file')

        if not upload_size or not temp_destination:
            return self.error('Invalid request. Please try again.')

        self.session['upload_file'].write(message)
        size = self.session['upload_file'].tell()

        percent = round((size / upload_size) * 100)
        await self.send_json({
            'action': 'progress',
            'percent': percent,
            'file_size': size
        })

        if size >= upload_size:
            self.session['upload_file'].flush()
            file_name = await self.handle_complete(self.session['upload_file'])

            await self.send_json({
                'action': 'complete',
                'file_size': size,
                'file_name': file_name
            }, close=True)
Run Code Online (Sandbox Code Playgroud)