Skip to content

Instantly share code, notes, and snippets.

@dyus
Last active December 4, 2016 09:58
Show Gist options
  • Save dyus/60d95f4fcfc6e276bac92781343de5f0 to your computer and use it in GitHub Desktop.
Save dyus/60d95f4fcfc6e276bac92781343de5f0 to your computer and use it in GitHub Desktop.
drf Base64Field with optional format
import base64
import binascii
from django.core.files.base import ContentFile
from django.utils import six
from rest_framework.exceptions import ValidationError
from rest_framework.fields import FileField
class Base64FieldMixin:
EMPTY_VALUES = (None, '', [], (), {})
def __init__(self, *args, **kwargs):
self.represent_in_base64 = kwargs.pop('represent_in_base64', False)
super(Base64FieldMixin, self).__init__(*args, **kwargs)
def to_internal_value(self, base64_data):
# Check if this is a base64 string
if base64_data in self.EMPTY_VALUES:
return None
if isinstance(base64_data, six.string_types):
# Strip base64 header.
if ';base64,' in base64_data:
header, base64_data = base64_data.split(';base64,')
try:
base64_data, file_name = base64_data.split(';file_name')
except ValueError:
raise ValidationError('Does not provide file name at the end of base64 string.'
'Supported format is '
'"base64string;file_name:name_with_file_extension".'
'Example "5647676isoiuahkdjvbsad;filename:my_file.pdf')
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(base64_data)
except (TypeError, binascii.Error):
raise ValidationError('Invalid base64 encoding')
data = ContentFile(decoded_file, name=file_name)
return super(Base64FieldMixin, self).to_internal_value(data)
raise ValidationError('This is not an base64 string')
def to_representation(self, file):
if self.represent_in_base64:
try:
with open(file.path, 'rb') as f:
return base64.b64encode(f.read()).decode()
except Exception:
raise IOError("Error encoding file")
else:
return super(Base64FieldMixin, self).to_representation(file)
class Base64Field(Base64FieldMixin, FileField):
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment