How to find file mimetype from binaryfield

Viewed 96

I have a file model with a binary field

class File(models.Model):
    id = models.AutoField(primary_key=True)
    file = models.BinaryField()
    name = models.TextField(null=False, blank=False)

I created a view that renders the file by id

def media(request, file_id):
    file = get_object_or_404(File, id=file_id)
    content = file.file
    return FileResponse(content, as_attachment=False, filename=file.name)

This is the output I get

%PDF-1.4 3 0 obj <>>><>>>] /Contents 4 0 R>> endobj 4 0 obj <> stream x�3R��2�35W(�*T0P�R0T(�Y@���@QC= PA�J��� �1Tp�W� �+R@&�ҹ6f� endstream endobj 1 0 obj <> endobj 5 0 obj <>/Group <> /Length 19219 >> stream x��}K�m�U����F�?��{9���������h�(�U��+�[�z;��A�����HI'4h#z��

When the file type is already known, I can manually set content_type to either application/pdf, image/png... But this is a BinaryField and I have no idea what the user uploaded. How can I get the correct mimetype regardless of the file type ?

1 Answers

You can make use of the python-magic package [pypi] to guess the MIME-type. You install this (in your virtual environment) with:

pip3 install python-magic

Then you can guess the mimetype based on the bytestream

from io import BytesIO
from magic import from_buffer as mime_from_buffer

def media(request, file_id):
    file = get_object_or_404(File, id=file_id)
    content = file.file
    with BytesIO(content) as f:
        mimetype = mime_from_buffer(f.read(), mime=True)
    # …
    return FileResponse(content, as_attachment=False, filename=file.name)

But this is a guess, not all files have a header that makes it clear what sort of data they are carrying, so in the end the guess can be incorrect.

I have a file model with a binary field

It is often not a good idea to store large binary streams in the database. A database is often not very good in storing huge amounts of (binary) data, and often the database will be slower in retrieving, storing, etc. files than the filesystem. That is why a FileField [Django-doc] will store in the database the path where to retrieve the file, and store the file content itself on a filesystem, or a dedicated storage server.

Related