Search code examples
djangoserializationdjango-rest-framework

Why coming this error: UnicodeDecodeError at /api/image/


My goal is to show the image's URL in response but it's not working. I getting errors. Here actually is it possible to return request.data.get('img')? Can you please give me a solution?

serializer.py:

class ImageSerializer(serializers.Serializer):
    img = serializers.ImageField(required=False)

views.py:

class ImageView(APIView):
   def post(self, request):
        serializer = ImageSerializer(data=request.data)
        return Response(
            {
                "processed_image_data": request.data.get('img')
            }, 
            status=status.HTTP_200_OK
        )

errors:

UnicodeDecodeError at /api/image/
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
Request Method: POST
Request URL:    http://127.0.0.1:8000/api/image/
Django Version: 4.2
Exception Type: UnicodeDecodeError
Exception Value:    
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
Exception Location: D:\23_Spondon-Bhai\2_Image-Process\venv\lib\site-packages\rest_framework\utils\encoders.py, line 50, in default
Raised during:  app.views.ImageView
Python Executable:  D:\23_Spondon-Bhai\2_Image-Process\venv\Scripts\python.exe
Python Version: 3.9.5
Python Path:    
['D:\\23_Spondon-Bhai\\2_Image-Process',
 'c:\\users\\dcl\\appdata\\local\\programs\\python\\python39\\python39.zip',
 'c:\\users\\dcl\\appdata\\local\\programs\\python\\python39\\DLLs',
 'c:\\users\\dcl\\appdata\\local\\programs\\python\\python39\\lib',
 'c:\\users\\dcl\\appdata\\local\\programs\\python\\python39',
 'D:\\23_Spondon-Bhai\\2_Image-Process\\venv',
 'D:\\23_Spondon-Bhai\\2_Image-Process\\venv\\lib\\site-packages']
Server time:    Wed, 19 Apr 2023 17:23:42 +0000
Unicode error hint
The string that could not be encoded/decoded was: ����

Traceback Switch to copy-and-paste view
D:\23_Spondon-Bhai\2_Image-Process\venv\lib\site-packages\django\core\handlers\exception.py, line 55, in inner
        return inner
    else:
        @wraps(get_response)
        def inner(request):
            try:
                response = get_response(request) …
            except Exception as exc:
                response = response_for_exception(request, exc)
            return response
        return inner
Local vars
D:\23_Spondon-Bhai\2_Image-Process\venv\lib\site-packages\django\core\handlers\base.py, line 220, in _get_response
                self.check_response(
                    response,
                    middleware_method,
                    name="%s.process_template_response"
                    % (middleware_method.__self__.__class__.__name__,),
                )
            try:
                response = response.render() …
            except Exception as e:
                response = self.process_exception_by_middleware(e, request)
                if response is None:
                    raise
        return response
Local vars

Solution

  • The issue you're encountering is because the response data contains binary image data, which cannot be directly included in a JSON response. Instead, you should convert the image data to a format that can be included in a JSON response, such as base64. You can try something as follows

    import base64
    from rest_framework.parsers import MultiPartParser
    
    class ImageView(APIView):
        parser_classes = (MultiPartParser,)
    
        def post(self, request):
            serializer = ImageSerializer(data=request.data)
            if serializer.is_valid():
                img = serializer.validated_data.get('img')
                img_format = img.image.format.lower()
                img_data = img.read()
                base64_img_data = base64.b64encode(img_data).decode('utf-8')
                return Response(
                    {
                        "processed_image_data": f"data:image/{img_format};base64,{base64_img_data}"
                    }, 
                    status=status.HTTP_200_OK
                )
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)