Search code examples
djangodjango-storage

Django File Storage: Add passwords to file names


We use Python Django.

I want to store user-uploaded files in the following way:

/<INTEGER>/<HASH>/<FILE>

<INTEGER> is a subfolder which is meant to contain max 1000 files.

<HASH> is a secret code individual for each file, to prevent hackers to download a somebody's other file from our HTTPS server.

<FILE> is the filename.

How to write a Django storage implementing this?

First, can I derive my class from django.core.files.storage.FileSystemStorage or I need to derived from django.core.files.storage.Storage directly?

Second, which methods should I override? Should I override save? It seems yes, because it is best to generate the hash only when saving, but I am unsure I can do in save what I need. What about overriding _save? Also: what's about overriding get_available_name and/or generate_filename? They seem not be quite tailored to my needs, because it would be better to generate the hash only when actually saving the file, not just when considering its name.

So, what to do?


Solution

  • I would go for generate_filename in django.core.files.storage.FileSystemStorage. I find it more appropriate since than I still have the nice safety cushion in get_available_name. I also wouldn't worry about getting filename in cases when the file is not being saved, just need to make sure that the hash generating is cheap enough.


    # settings.py
    
    DEFAULT_FILE_STORAGE = 'app.storage.CustomStorage'
    

    # app/storage.py
    
    from datetime import datetime
    import hashlib
    import random
    
    from django.core.files.storage import FileSystemStorage
    
    
    class CustomStorage(FileSystemStorage):
        def generate_filename(self, filename):
            # implement smarter hash creation method here
            some_hash = hashlib.md5('{}-{}'.format('filename', datetime.now().isoformat())).hexdigest()
    
            return '{0}/{1}/{2}'.format(random.randint(0, 1000), some_hash, filename)