programing

Django REST Framework 업로드 이미지: "제출된 데이터가 파일이 아닙니다."

muds 2023. 3. 2. 22:41
반응형

Django REST Framework 업로드 이미지: "제출된 데이터가 파일이 아닙니다."

저는 Django에서 파일을 업로드하는 방법을 고민하고 있는데, 여기서 다음과 같은 오류로 인해 중대한 문제가 발생했습니다.

제출된 데이터는 파일이 아닙니다.폼의 부호화 타입을 확인합니다.

자세한 내용은 다음과 같습니다.


주의: Django Rest Framework Image Field도 살펴보고

serializer = ImageSerializer(data=request.data, files=request.FILES)

하지만 나는 이해한다

유형 오류:__init__()예기치 않은 키워드 인수 'files'를 받았습니다.


나는 가지고 있다ImageDjango REST 프레임워크를 통해 소통하고 싶은 모델:

models.py

class Image(models.Model):
    image = models.ImageField(upload_to='item_images')
    owner = models.ForeignKey(
        User, related_name='uploaded_item_images',
        blank=False,
    )
    time_created = models.DateTimeField(auto_now_add=True)

serializers.py

class ImageSerializer(serializers.ModelSerializer):
    image = serializers.ImageField(
        max_length=None, use_url=True,
    )

    class Meta:
        model = Image
        fields = ("id", 'image', 'owner', 'time_created', )

설정을 지정합니다.화이

'DEFAULT_PARSER_CLASSES': (
    'rest_framework.parsers.JSONParser',
    'rest_framework.parsers.FormParser',
    'rest_framework.parsers.MultiPartParser',
),

프론트 엔드(Angular 사용)JS 및angular-restmod또는$resource)의 송신JSON로의 데이터.owner그리고.image폼의 경우:

입력:

{"owner": 5, "image": "data:image/jpeg;base64,/9j/4QqdRXhpZgAATU0A..."}

백엔드에서request.data드라마들.

{u'owner': 5, u'image': u'data:image/jpeg;base64,/9j/4QqdRXhpZgAATU0AKgAAA..."}

그러나ImageSerializer(data=request.data).errors에러를 나타냅니다.

ReturnDict([('image', [u'The submitted data was not a file. Check the encoding type on the form.'])])

오류를 수정하려면 어떻게 해야 하나요?


편집: JS 부품

관련 프런트 엔드 코드는 다음 두 부분으로 구성됩니다.angular-file-dnd directive(여기서 이용 가능) 파일을 페이지에 드롭하고angular-restmodCRUD 동작은 다음과 같습니다.

<!-- The template: according to angular-file-dnd, -->
<!-- it will store the dropped image into variable $scope.image -->
<div file-dropzone="[image/png, image/jpeg, image/gif]" file="image" class='method' data-max-file-size="3" file-name="imageFileName">
  <div layout='row' layout-align='center'>
    <i class="fa fa-upload" style='font-size:50px;'></i>
  </div>
  <div class='text-large'>Drap & drop your photo here</div>
</div>



# A simple `Image` `model` to perform `POST`
$scope.image_resource = Image.$build();

$scope.upload = function() {
  console.log("uploading");
  $scope.image_resource.image = $scope.image;
  $scope.image_resource.owner = Auth.get_profile().user_id;
  return $scope.image_resource.$save();
};


문제에 대한 업데이트: 현재 사용으로 전환했습니다.ng-file-upload이미지 데이터를 올바른 형식으로 전송합니다.

당신이 직면하고 있는 문제는 Django REST 프레임워크가 표준 파일 업로드 방식을 통해 파일이 멀티파트데이터로 업로드될 것으로 예상한다는 것입니다.이것은 보통 필드이지만 JavaScript 개체는 AJAX에서도 작동합니다.

기본적으로 지원되지 않는 raw 파일이 아닌 base64 인코딩된 문자열을 사용하여 파일을 업로드하려고 합니다.실제 구현도 있지만 가장 유망한 은 풀 요청을 통해 이루어졌습니다.

대부분 Django REST 프레임워크 2.x용으로 설계되었기 때문에 풀 요청에서 개선하여 DRF 3과 호환되는 것을 만들었습니다.

serializers.py

from rest_framework import serializers    

class Base64ImageField(serializers.ImageField):
    """
    A Django REST framework field for handling image-uploads through raw post data.
    It uses base64 for encoding and decoding the contents of the file.

    Heavily based on
    https://github.com/tomchristie/django-rest-framework/pull/1268

    Updated for Django REST framework 3.
    """

    def to_internal_value(self, data):
        from django.core.files.base import ContentFile
        import base64
        import six
        import uuid

        # Check if this is a base64 string
        if isinstance(data, six.string_types):
            # Check if the base64 string is in the "data:" format
            if 'data:' in data and ';base64,' in data:
                # Break out the header from the base64 content
                header, data = data.split(';base64,')

            # Try to decode the file. Return validation error if it fails.
            try:
                decoded_file = base64.b64decode(data)
            except TypeError:
                self.fail('invalid_image')

            # Generate file name:
            file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
            # Get the file name extension:
            file_extension = self.get_file_extension(file_name, decoded_file)

            complete_file_name = "%s.%s" % (file_name, file_extension, )

            data = ContentFile(decoded_file, name=complete_file_name)

        return super(Base64ImageField, self).to_internal_value(data)

    def get_file_extension(self, file_name, decoded_file):
        import imghdr

        extension = imghdr.what(file_name, decoded_file)
        extension = "jpg" if extension == "jpeg" else extension

        return extension

이것은 표준의 대체에 사용되어야 한다.ImageFieldDjango REST 프레임워크에 의해 제공됩니다.그러면 시리얼라이저는

class ImageSerializer(serializers.ModelSerializer):
    image = Base64ImageField(
        max_length=None, use_url=True,
    )

    class Meta:
        model = Image
        fields = ("id", 'image', 'owner', 'time_created', )

이를 통해 base64로 인코딩된 문자열 또는 표준 문자열을 지정할 수 있습니다.Blob일반적으로 Django REST 프레임워크가 예상하는 객체입니다.

저는 며칠 전에 같은 문제에 부딪혔어요.파일 업로드를 처리하기 위한 django rest 프레임워크 뷰입니다.

views.py

class PhotoUploadView(APIView):
    parser_classes = (FileUploadParser,)

    def post(self, request):
        user = self.request.user
        if not user:
            return Response(status=status.HTTP_403_FORBIDDEN)
        profile  = None
        data     = None
        photo    = None

        file_form = FileUploadForm(request.POST,request.FILES)
        if file_form.is_valid():
            photo = request.FILES['file']
        else:
            return Response(ajax_response(file_form),status=status.HTTP_406_NOT_ACCEPTABLE)

        try:
            profile = Organizer.objects.get(user=user)
            profile.photo = photo
            profile.save()
            data    = OrganizersSerializer(profile).data
        except Organizer.DoesNotExist:
            profile = Student.objects.get(user=user)
            profile.photo = photo
            profile.save()
            data    = StudentsSerializer(profile).data

        return Response(data)

프런트 엔드에서 angular-file-upload lib를 사용했습니다.

여기 제 파일 입력이 있습니다.

<div ng-file-drop="" ng-file-select="" ng-model="organizer.photo" class="drop-box" drag-over-class="{accept:'dragover', reject:'dragover-err', delay:100}" ng-multiple="false" allow-dir="true" accept="image/*">
                                    Drop Images or PDFs<div>here</div>
</div>

그리고 여기 제 업로드 서비스가 있습니다.

main.discloss.main.discloss.

(function () {
  'use strict';

  angular
    .module('trulii.utils.services')
    .factory('UploadFile', UploadFile);

  UploadFile.$inject = ['$cookies', '$http','$upload','$window','Authentication'];

  /**
  * @namespace Authentication
  * @returns {Factory}
  */
  function UploadFile($cookies, $http,$upload,$window,Authentication) {
    /**
    * @name UploadFile
    * @desc The Factory to be returned
    */


    var UploadFile = {
      upload_file: upload_file,
    };
    
    return UploadFile;


    function upload_file(file) {


      return $upload.upload({
        url: '/api/users/upload/photo/', // upload.php script, node.js route, or servlet url
        //method: 'POST' or 'PUT',
        //headers: {'Authorization': 'xxx'}, // only for html5
        //withCredentials: true,
        file: file, // single file or a list of files. list is only for html5
        //fileName: 'doc.jpg' or ['1.jpg', '2.jpg', ...] // to modify the name of the file(s)
        //fileFormDataName: myFile, // file formData name ('Content-Disposition'), server side request form name
                                    // could be a list of names for multiple files (html5). Default is 'file'
        //formDataAppender: function(formData, key, val){}  // customize how data is added to the formData. 
                                                            // See #40#issuecomment-28612000 for sample code

      })

    }


  }



})();

언급URL : https://stackoverflow.com/questions/28036404/django-rest-framework-upload-image-the-submitted-data-was-not-a-file

반응형