Upload files to Django Rest Framework using AngularJS

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:

<br />
angular.controller('ImageUploadFormCtrl', function($scope, Photo){<br />
  $scope.submitForm = function(isValid){<br />
    if(isValid){<br />
      f = new FileReader(); // or $window.FileReader()</p>
<p>      f.onload = function () {<br />
        $scope.formData.image = f.result; // This is a base64 string</p>
<p>        Photo.save({}, $scope.formData).$promise.then(function(data){<br />
          // 200 Response<br />
          alert('Client image successfully updated.');<br />
        }, function(error){<br />
          // 400 Response<br />
          console.log('Error', error);<br />
          alert('An error has ocurred.');<br />
        })<br />
      };      </p>
<p>      // Read the file selected on the field with ID &quot;image-field&quot;<br />
      f.readAsDataURL(document.getElementById('image-field').files[0]);<br />
    }<br />
  }<br />
});<br />

On the server side on my Django app, specifically on the serializers.py file:

<br />
import base64, uuid<br />
from django.core.files.base import ContentFile</p>
<p>class Base64ImageField(serializers.ImageField):<br />
  def to_internal_value(self, data):<br />
    if isinstance(data, basestring) and data.startswith('data:'): # You can change &quot;data:&quot; to &quot;data/image:&quot;<br />
      format, imgstr = data.split(';base64,')<br />
      ext  = format.split('/')[-1]<br />
      id   = uuid.uuid4()<br />
      data = ContentFile(base64.b64decode(imgstr), name=id.urn[9:])</p>
<p>    return super(Base64ImageField, self).to_internal_value(data)</p>
<p>class PhotoSerializer(serializers.ModelSerializer):<br />
  image = Base64ImageField(allow_empty_file=False)</p>
<p>  class Meta:<br />
    fields           = ('id', 'image')<br />
    model            = Photo<br />
    read_only_fields = ('id', )<br />

I found out that this is the cleaner way to do this. If you have another alternative, please share it.




Irving Kcam

Full Stack Developer. AWS lover, Django ninja, Angular enthusiast.

No Comments


You can leave the first : )



Leave a Reply