существуют ли какие-либо хитроумные способы сохранения файлов с помощью веб-сокета в Django?

#django #django-channels

#django #django-каналы

Вопрос:

Я создал сайт чата и думаю, что могу добавить функцию отправки файлов помимо сообщения. Но, похоже, веб-сокет не может отправлять файлы или изображения. Мое решение заключается в том, что при отправке файла я использую api, а затем извлекаемые сообщения и файлы переупорядочиваются по метке времени. Но если есть лучшие способы добиться этого, я действительно хочу знать.

Итак, мой вопрос

  1. Можно ли отправлять файлы с помощью веб-сокета и получать их с помощью WebsocketConsumer?
  2. Есть ли какие-либо способы объединить эти два процесса? (напр. вы отправляете предварительную ссылку на файлы и сохраняете их как FileField?)

Модель

 from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()


class Contact(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='contact_user')
    friends = models.ManyToManyField('self', blank=True, related_name='friends')


    def __str__(self):
        return self.user.name

class Message(models.Model):
    contact = models.ForeignKey(Contact, related_name='message', on_delete=models.CASCADE)
    content = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.contact.user.name

class File(models.Model):
    contact = models.ForeignKey(Contact, related_name='file', on_delete=models.CASCADE)
    file = models.FileField()
    timestamp = models.DateTimeField(auto_now_add=True)

class Chat(models.Model):
    participants = models.ManyToManyField(Contact, related_name='chats')
    messages = models.ManyToManyField(Message, blank=True)
    files = models.ManyToManyField(File, blank=True, null=True)
    timestamp = models.DateTimeField(auto_now_add=True)


    def last_30_messages(self):
        return self.messages.order_by('-timestamp').all()[:30]


    def __str__(self):
        return "{}".format(self.pk)
 

Я не знаю, какая информация необходима, чтобы разобраться в этом, поэтому я вставляю только модель. Если что-то неясно, дайте мне знать.

Спасибо 🙂

Комментарии:

1. @minglyu Это сработало! Спасибо! если вы ответите на мой вопрос ниже. Я могу принять ваш ответ.

Ответ №1:

Вы можете кодировать изображение в base64 формате во внешнем интерфейсе и decode на стороне сервера, я бы посоветовал сжать изображение в браузере, если вас не очень волнует качество изображения, поскольку это может уменьшить размер изображения до большого содержимого.

На стороне сервера вы можете читать декодированные байты как ContentFile , чтобы он мог отлично работать с Django ORM:

 from django.core.files.base import ContentFile
import base64

def base64_decode(data, name):
    '''decode the base64 string and create a compatible 
       file that Django recognize
    '''
    format, imgstr = data.split(';base64,') 
    ext = format.split('/')[-1]
    data = ContentFile(base64.b64decode(imgstr), name=name   '.'   ext)
    return data

# save the file
file = base64_decode(message, 'file_name')
Yourmodel.objects.create(file=file, ...)