Skip to content

Instantly share code, notes, and snippets.

@cellofellow
Forked from klipstein/b64field.py
Last active December 16, 2015 20:29
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cellofellow/5493290 to your computer and use it in GitHub Desktop.
Save cellofellow/5493290 to your computer and use it in GitHub Desktop.
import base64
import os
import mimetypes
from django.core.files.uploadedfile import SimpleUploadedFile
from tastypie import fields
class Base64FileField(fields.FileField):
"""
A django-tastypie field for handling file-uploads through raw post data.
It uses base64 for en-/decoding the contents of the file.
Usage:
class MyResource(ModelResource):
file_field = Base64FileField("file_field")
class Meta:
queryset = ModelWithFileField.objects.all()
In the case of multipart for submission, it would also pass the filename.
By using a raw post data stream, we have to pass the filename within our
file_field structure:
file_field = {
"name": "myfile.png",
"file": "longbas64encodedstring",
"content_type": "image/png" # on hydrate optional
}
Your file_field will by dehydrated in the above format if the return64
keyword argument is set to True on the field, otherwise it will simply
return the URL.
"""
def __init__(self, **kwargs):
self.return64 = kwargs.pop('return64', False)
super(Base64FileField, self).__init__(**kwargs)
def _url(self, obj):
instance = getattr(obj, self.instance_name, None)
try:
url = getattr(instance, 'url', None)
except ValueError:
url = None
return url
def dehydrate(self, bundle, **kwargs):
if not self.return64:
return self._url(bundle.obj)
else:
if (not self.instance_name in bundle.data
and hasattr(bundle.obj, self.instance_name)):
file_field = getattr(bundle.obj, self.instance_name)
if file_field:
content_type, encoding = mimetypes.guess_type(
file_field.file.name)
b64 = open(
file_field.file.name, "rb").read().encode("base64")
ret = {"name": os.path.basename(file_field.file.name),
"file": b64,
"content-type": (content_type or
"application/octet-stream")}
return ret
return None
def hydrate(self, obj):
value = super(Base64FileField, self).hydrate(obj)
if value and isinstance(value, dict):
return SimpleUploadedFile(value["name"],
base64.b64decode(value["file"]),
value.get("content_type",
"application/octet-stream"))
elif isinstance(value, basestring):
if value == self._url(obj.obj):
return getattr(obj.obj, self.instance_name).name
return value
else:
return None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment