Last active
December 4, 2016 09:58
-
-
Save dyus/60d95f4fcfc6e276bac92781343de5f0 to your computer and use it in GitHub Desktop.
drf Base64Field with optional format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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