(Swift) upload Image to backend (Django Rest Framework) not working and Worked in (Postman) & (Admin Page)

Published

Trying to Upload Image From Swift APP to Django backend with (DRF and Pillow )

models.py

class Profile(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.CharField(max_length=300, blank=True)
    user_img = models.ImageField(upload_to='images/', blank=True, null= True)

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

url.py

from django.urls import path
from . import views

urlpatterns = [
    path('user', views.PUser.as_view()),
]

view.py

class PUser(APIView):

    def patch(self, request, format=None):
    
        try:
            userData = User.objects.get(pk=6)
        
            serializer = serializers.PUserSerializer(userData, data=request.data, partial=True)
        
        if serializer.is_valid():
            serializer.save()

            return Response(serializer.data)
        else:
            return Response(serializer.errors)

    except Exception as e:

        return Response("PATCH Error : %s" % str(e))
        

serializers.py

class PUserSerializer(serializers.ModelSerializer):

profile = ProfileSerializer()

class Meta:
    model = User
    fields = ["first_name", "last_name","username","profile"]

def update(self, instance, validated_data):
    
    instance.username = validated_data.get('username', instance.username)
    instance.first_name = validated_data.get('first_name', instance.first_name)
    instance.last_name = validated_data.get('last_name', instance.last_name)
    instance.save()

    if validated_data.get('profile') is not None:
        profile_data = validated_data.pop('profile')
        Profile.objects.get_or_create(user=instance)
        profile = instance.profile
        profile.bio = profile_data.get('bio',profile.bio)
        profile.user_img = profile_data.get('user_img',profile.user_img)
        profile.save()
        
    return instance 

tested on Django Admin Page working fine I can upload image.

tested on Postman and its working fine I can upload image.

when I try to upload from swift I got invalid_image

I am Taking UIImage and converted using pngData and send it in URLSession:
param["src"] contains UIImage

var request = URLRequest(url: URL(string: ServerURL)!,timeoutInterval: Double.infinity)
    let boundary = "Boundary-(UUID().uuidString)"
    request.addValue("multipart/form-data; boundary=(boundary)", forHTTPHeaderField: "Content-Type")
    request.addValue("Bearer " + myToken, forHTTPHeaderField: "Authorization")
    request.httpMethod = "PATCH"
var body = ""
for param in parameters {
        if param["disabled"] == nil {
            let paramName = param["key"]!
            body += "--(boundary)rn"
            body += "Content-Disposition: form-data; name="(paramName)""
            if param["contentType"] != nil {
                body += "rnContent-Type: (param["contentType"] as! String)"
            }
            let paramType = param["type"] as! String
            if paramType == "text" {
                let paramValue = param["value"] as! String
                body += "rnrn(paramValue)rn"
            } else {
            let paramSrc = param["src"] as! UIImage
            let fileData = (String(data: fileData, encoding: .utf8) ?? "Converting to UTF8 Fail") as String
            body += "; filename="myImg.png"rn"
            body += "Content-Type: image/pngrnrn(fileData)rn"
                        

Print Request Output:

HEADERS
Optional(["Authorization": "Bearer xxxxx", "Content-Type": "multipart/form-data; boundary=Boundary-xxxx-xxxxx-xxxxx-xxxxx-x"])

BODY

–Boundary-xxxx-xxxxx-xxxxx-xxxxx-x

Content-Disposition: form-data; name="first_name"

myfirstname

–Boundary-xxxx-xxxxx-xxxxx-xxxxx-x

Content-Disposition: form-data; name="last_name"

mylastname

–Boundary-xxxx-xxxxx-xxxxx-xxxxx-x

Content-Disposition: form-data; name="username"

myusernamehere

–Boundary-xxxx-xxxxx-xxxxx-xxxxx-x

Content-Disposition: form-data; name="profile.bio"

my profile bio here

–Boundary-xxxx-xxxxx-xxxxx-xxxxx-x

Content-Disposition: form-data; name="profile.user_img"; filename="avatar.jepg"

Content-Type: image/jpeg

4AAQSkZJRgABAgEASABIAAD/4QDKRXhpZgAATU0AKgAAAAgABgESAAM large text here

–Boundary-xxxx-xxxxx-xxxxx-xxxxx-x

I also try without base64EncodedString so it will be less size and still getting same error

Checked paramSrc and its content the image but fileData got nil

I have try :

let fileData = paramSrc.pngData()! as NSData

and fileData was contain the data not nil but still getting

ErrorDetail(string='Upload a valid image. The file you uploaded was either not an image or a corrupted image.', code='invalid_image')

SOLVE it :

thanks for @pastre for helping find where is the problem happen

I just change the body from string to data

var body = Data()

and then

 if let fileData = paramSrc.pngData() {
                        body.append("; filename="blah.png"rn".data(using: .utf8)!)
                        body.append("Content-Type: "content-type header"rnrn".data(using: .utf8)!)
                        body.append(fileData)
                    }

Source: Swift Questions

Answers

Leave a Reply

Your email address will not be published. Required fields are marked *

Still Have Questions?


Our dedicated development team is here for you!

We can help you find answers to your question for as low as 5$.

Contact Us
faq