Django REST Framework получил файл JPEG в виде строки в ImageField - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть модель в Django, например:

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

from datetime import datetime
# Create your models here.

class UserDetails(models.Model):

    def getFileName(self, filename):
        return 'profile_pics/'+str(self.user.id)+'/'+filename

    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    profile_picture = models.ImageField(upload_to=getFileName, blank = True)
    country = models.CharField(max_length = 50, default='UK')
    gender = models.CharField(max_length=10, default='NA')
    birthday = models.DateField(default=datetime.now())

    phone = models.CharField(max_length=15)

    verified = models.BooleanField(default=False)

    def __str__(self):

        try:
            return self.user.username
        except:
            return 'Deleted User - '+str(self.phone)

Затем я создал REST API , который принимает Multipart запросы на создание нового пользователя. а также сохранить user_details для пользователя. Я делаю многочастный POST-запрос из моего приложения во флаттере с изображением для изображения профиля. Изображение приходит в теле запроса в виде строки, а не в виде файла, где я мог бы прочитать его с помощью request.FILES['profile_picture']. Тело запроса, который я получаю, выполняя print(request.data), выглядит следующим образом:

Data: <QueryDict: {
'username': ['jonsnow'], 
'first_name': ['Jon'], 
'last_name': ['Snow'], 
'email': ['jonsnow@got.com'], 
'password': ['jonsnow'], 
'country': ['UK'], 
'gender': ['Male'], 
'birthday': ['2020-4-28'], 
'phone': ['5198189849'], 
'profile_picture': ['����\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00��\x00�\x00\t\x06\x07\x08\x07\x06\t\x08\x07\x08\n\n\t\x0b\r\x16\x0f\r\x0c\x0c\r\x1b\x14\x15\x10\x16 \x1d"" \x1d\x1f\x1f$(4,$&1\'\x1f\x1f-=-157:::#+?D?8C49:7\x01\n\n\n\r\x0c\r\x1a\x0f\x0f\x1a7%\x1f%77777777777777777777777777777777777777777777777777��\x00\x11\x08\x019\x01�\x03\x01"\x00\x02\x11\x01\x03\x11\x01��\x00\x1c\x00\x00\x02\x03\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x04\x02\x05\x06\x01\x07\x00\x08��\x00Q\x10\x00\x02\x01\x03\x02\x03\x05\x04\x06\x06\x07\x07\x03\x03\x01\t\x01\x02\x03\x00\x04\x11\x12!\x051A\x06\x13"Qa2q��\x14B����\x07#3Rr�\x154Sbs��\x16$C����5��%c�DtEFd����\x17��\x00\x1a\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06��\x00(\x11\x01\x01\x00\x02\x01\x04\x02\x02\x02\x02\x03\x01\x00\x00\x00\x00\x00\x01\x02\x11\x03\x12!1A\x04\x13\x14Q\x05"aqBR�\x15��\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00�Cl�0ɵX��¸�iB�k; ...\uebe8?��']
}>

И print(request.FILES) выглядит так: Files: <MultiValueDict: {}>

Итак, я сделал Multipart REST API для обработки этого запроса, например:

class SignUp(APIView):
    parser_classes = [MultiPartParser,]
    authentication_classes = [CsrfExemptSessionAuthentication]
    permission_classes = [AllowAny]

    def post(self, request, format=None):

        data = request.data

        print('\n\nFiles: '+str(request.FILES)+'\n\n');
        print('\n\nData: '+str(data)+'\n\n');
        print('\n\nData: '+str(request.META)+'\n\n');

        ## Creating a basic user
        user = User.objects.create_user(username=data['username'], first_name = data['first_name'], last_name = data['last_name'], email = data['email'], password = data['password'])
        user.save()

        user_details = UserDetails()
        user_details.user = user

        rec_img_str = data['profile_picture']
        rec_img_bytes = rec_img_str.encode('utf-8')
        rec_img_writer = BytesIO(rec_img_bytes)
        uploaded_img = InMemoryUploadedFile(rec_img_writer, None, 'sample.jpg', 'image/jpeg', None, 'utf-8')

        user_details.profile_picture = uploaded_img
        user_details.country = data['country']
        user_details.gender = data['gender']
        user_details.birthday = datetime.strptime(data['birthday'], '%Y-%m-%d').date()
        user_details.phone = data['phone']
        user_details.verified = False
        user_details.save()

        return Response({'Message': 'Profile Created Successfully'})

Здесь я прочитал JPG изображение, которое появляется в виде строки в поле profile_picture, преобразовал его в байтовую форму, поместил в BytesIO(), а затем сохранил его в user_details.profile_picture как InMemoryUploadedFile. Он сохраняется как sample.jpg в моем каталоге MEDIA, но когда я пытаюсь открыть его, он появляется как пустое изображение.

Итак, как мне сохранить изображение JPEG, которое поступает в виде строки, в ImageField in Django?

Вот мой код Flutter , если это необходимо для справки:

void submit() async {
    MultipartRequest request = MultipartRequest("POST",
        Uri.parse("http://10.0.2.2:8000/services/authentication/signup/"));

    request.fields['username'] = this.username.text;
    request.fields['first_name'] = this.first_name.text;
    request.fields['last_name'] = this.last_name.text;
    request.fields['email'] = this.email.text;
    request.fields['password'] = this.password.text;

    request.fields['country'] = "UK";
    request.fields['gender'] = this.gender;
    String birthdayStr = "${birthday.year}-${birthday.month}-${birthday.day}";
    request.fields['birthday'] = birthdayStr;
    request.fields['phone'] = this.phone_no.text;

    if (this.profilePicture != null) {
      print('Profile picture available');
      print(this.profilePicture.path);
      request.files.add(
        await MultipartFile.fromBytes(
          'profile_picture',
          await this.profilePicture.readAsBytes(), //this.profilePicture is a File
          contentType: MediaType('image', 'jpeg'),
        ),
      );
    }

    StreamedResponse resp = await request.send();

    if (resp.statusCode < 200 || resp.statusCode >= 400) {
      print('There was an error in making the SignUp Request');
      print('Status code: ${resp.statusCode}');
    } else {
      Navigator.pop(context);
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...