简体   繁体   English

UnicodeDecodeError - Django 上传文件

[英]UnicodeDecodeError - Django Upload file

I'm using Django Rest Framework, and with a simple form on the frontend I upload some data, and attachments to a model in Django.我正在使用 Django Rest Framework,并在前端使用一个简单的表单,我将一些数据和附件上传到 Django 中的模型。

I store the files at AWS S3, and I'm using Django S3 Storage.我将文件存储在 AWS S3 中,并且我正在使用 Django S3 存储。

When I upload a file I get an UnicodeDecodeError as follows.当我上传文件时,我得到一个 UnicodeDecodeError 如下。 (See bottom for trace) (见底部的踪迹)

My file model我的档案模型

class JourAttachment(models.Model):
    jourreport = models.ForeignKey(JourReport,related_name="jourattachments", on_delete=models.CASCADE)
    file = models.FileField(null=False)

View看法

class JourReportListView(APIView):
    serializer_class = JourReportListSerializer
    permission_classes = (IsAuthenticated, )
    parser_classes = (MultiPartParser,)
    

    def post(self,request,*args, **kwargs):
        
        user_making_request = request.user
        if not user_is_admin(user_making_request):
            return UserNotAdminResponse()

        attachments = request.FILES.getlist('attachment', None)
        
        serializer = JourReportCreateUpdateSerializer(data=request.data,partial=True,context={'attachments': attachments})
        valid = serializer.is_valid(raise_exception=True)
        if valid:
            report = serializer.save()
            
            status_code = status.HTTP_201_CREATED
 
            #send_mail_with_jourreport(report)
            return SuccessfulResponse(data=request.data, message="Jour report successfully registered!" ,status_code=status_code)
    
        return ErrorResponse()

Serializer串行器

class JourReportCreateUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = JourReport
        fields = ('apartment_number', 'address', 'tenant_name','tenant_phone', 'debit_tenant','worker','total_hours', 'additional_workers','defect_description','actions_made','actions_to_be_made')

    

    def create(self, validated_data):
        users = []
        attachments = self.context['attachments']
        if "additional_workers" in validated_data:
            users = [w.id for w in validated_data["additional_workers"]]
            del validated_data["additional_workers"]
        
        report = JourReport.objects.create(**validated_data)
        
        for a in attachments:
            
            JourAttachment.objects.create(file=a,jourreport=report) # Add attachments to instance

        if(len(users) > 0):
            report.additional_workers.add(*users)

        return report

The model is correctly added and all files are stored, but either way I get an 500 response with UnicodeDecodeError Trace模型已正确添加并存储了所有文件,但无论哪种方式,我都会收到 UnicodeDecodeError Trace的 500 响应

Traceback (most recent call last):
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/rest_framework/response.py", line 70, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/rest_framework/renderers.py", line 100, in render
    ret = json.dumps(
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/rest_framework/utils/json.py", line 25, in dumps
    return json.dumps(*args, **kwargs)
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/__init__.py", line 234, in dumps
    return cls(
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/Users/jakobkarlstrand/Documents/Programming/weknowit/HaningeBostader/backend/venv/lib/python3.9/site-packages/rest_framework/utils/encoders.py", line 50, in default
    return obj.decode()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa2 in position 50: invalid start byte

I also have a custom S3 storage handler:我还有一个自定义 S3 存储处理程序:

class CustomS3Storage(S3Storage,ABC):

    def _save(self, name, content):
        """
        We create a clone of the content file as when this is passed to boto3 it wrongly closes
        the file upon upload where as the storage backend expects it to still be open
        """
        # Seek our content back to the start
        content.seek(0, os.SEEK_SET)

        # Create a temporary file that will write to disk after a specified size
        content_autoclose = self.new_temporary_file()

        # Write our original content into our copy that will be closed by boto3
        
        content_autoclose.write(content.read().strip())
        content_autoclose.file = content.file


        # Upload the object which will auto close the content_autoclose instance
        result = super()._save(strip_non_ascii(name), content_autoclose)

        # Cleanup if this is fixed upstream our duplicate should always close
        if not content_autoclose.closed:
            content_autoclose.close()
        

        return result

The problem was in the response:问题在于响应:

return SuccessfulResponse(data=request.data,message="Jour report successfully registered!" ,status_code=status_code)

I was returning the request data including the files, which raises the error.我正在返回包括文件在内的请求数据,这会引发错误。 Remove it, or serialize first to get rid of the error删除它,或者先序列化以摆脱错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM