Encoding the image to “base64”, send it to our DRF endpoint and on our DRF serializers change the ImageField to Base64ImageField was the implementation I used:
On the client side, on my angular app:
angular.controller('ImageUploadFormCtrl', function($scope, Photo){ $scope.submitForm = function(isValid){ if(isValid){ f = new FileReader(); // or $window.FileReader() f.onload = function () { $scope.formData.image = f.result; // This is a base64 string Photo.save({}, $scope.formData).$promise.then(function(data){ // 200 Response alert('Client image successfully updated.'); }, function(error){ // 400 Response console.log('Error', error); alert('An error has ocurred.'); }) }; // Read the file selected on the field with ID "image-field" f.readAsDataURL(document.getElementById('image-field').files[0]); } } });
On the server side on my Django app, specifically on the serializers.py
file:
import base64, uuid from django.core.files.base import ContentFile class Base64ImageField(serializers.ImageField): def to_internal_value(self, data): if isinstance(data, basestring) and data.startswith('data:'): # You can change "data:" to "data/image:" format, imgstr = data.split(';base64,') ext = format.split('/')[-1] id = uuid.uuid4() data = ContentFile(base64.b64decode(imgstr), name=id.urn[9:]) return super(Base64ImageField, self).to_internal_value(data) class PhotoSerializer(serializers.ModelSerializer): image = Base64ImageField(allow_empty_file=False) class Meta: fields = ('id', 'image') model = Photo read_only_fields = ('id', )
I found out that this is the cleaner way to do this. If you have another alternative, please share it.
1 Comment
[…] http://xploit29.com/2016/09/13/upload-files-to-django-rest-framework-using-angularjs/ […]