0

In python there is a nice library 'base64', with this module it's possible to encode/decode files based on the filename and the content. I'm developing an API which has the functionality to upload a file. I managed to write some code to encode and decode these files, but what is the correct way to send this encoded base64 message over a HTTP request?

  • Via a POST and just put the filename and encoded message into a post param?
  • Inside the headers?

Any ideas are welcome, if possible show a small http request how you should do it.

Sheena
  • 15,590
  • 14
  • 75
  • 113
user1839924
  • 31
  • 1
  • 2
  • 1
    You might want to read this first: http://stackoverflow.com/questions/8659808/how-does-http-file-upload-work – Udo Klein Apr 09 '13 at 08:43
  • I'm not interested in the fileupload, the point is that I need to transfer the file via an API. There is a possibility to pass the filename and the base64 encoded message via a seperate param, but i'm stuck on how to block files > 10MB for example – user1839924 Apr 09 '13 at 12:32

1 Answers1

2

I had to do this recently because django-tastypie does not support multipart/form-data. klipstein has created Base64FileField to support file uploades by using base64 encoding of file.

Here is an example based on Base64FileField:

#models.py
from django.db import models

class Person(models.Model):
    name = models.CharField("name", max_length=40)
    avatar = models.ImageField("avatar", upload_to="uploads/person_avatars")

    def __unicode__(self):
        return self.name

#views.py
import json
import base64
import sys
from django.core.files.uploadedfile import SimpleUploadedFile
from django.http import HttpResponse, HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt

from .models import Person

MAX_SIZE = 10*1024*1024 #10MB

@csrf_exempt
def save_person(request):
    if (request.method == "POST" and request.META.get("CONTENT_TYPE")
        == "application/json"):
        data = json.loads(request.raw_post_data)
        avatar = data.get("avatar")
        file = base64.b64decode(avatar["file"])
        if sys.getsizeof(file) > MAX_SIZE:
            response = {"error": {
                "code": "invalid_request",
                "message": "Max file size exceeded."
                }}
            return HttpResponseBadRequest(json.dumps(response),
                mimetype="application/json")

        person = Person(name=data.get("name"), avatar=SimpleUploadedFile(
            avatar["name"],
            file,
            getattr(avatar, "content_type", "application/octet-stream")))
        person.save()

        response = {"id": person.id, "name": person.name,
            "avatar": person.avatar.url}
        return HttpResponse(json.dumps(response), mimetype="application/json")

    response = {"error": {
        "code": "invalid_request",
        "message": "Method Not Allowed."
        }}
    return HttpResponseBadRequest(json.dumps(response),
        mimetype="application/json")

Here is example JSON body to be posted for above view

{
    "name": "Test User",
    "avatar": {
        "name": "myfile.png",
        "file": "a long base64 encoded string ",
        "content_type": "image/png"
    }
}

and example response is:

{
    "id": 1,
    "avatar": "/media/uploads/person_avatars/myfile.png",
    "name": "Test User"
}

What is the best way?

Not sure if this is the best way, but, it's simple and straightforward.

Community
  • 1
  • 1
pankaj28843
  • 2,458
  • 17
  • 34