[Django]-How to copy InMemoryUploadedFile object to disk

70đź‘Ť

âś…

This is similar question, it might help.

import os
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.conf import settings

data = request.FILES['image'] # or self.files['image'] in your form

path = default_storage.save('tmp/somename.mp3', ContentFile(data.read()))
tmp_file = os.path.join(settings.MEDIA_ROOT, path)
👤Davor Lucic

31đź‘Ť

As mentioned by @Sławomir Lenart, when uploading large files, you don’t want to clog up system memory with a data.read().

From Django docs :

Looping over UploadedFile.chunks() instead of using read() ensures
that large files don’t overwhelm your system’s memory

from django.core.files.storage import default_storage

filename = "whatever.xyz" # received file name
file_obj = request.data['file']

with default_storage.open('tmp/'+filename, 'wb+') as destination:
    for chunk in file_obj.chunks():
        destination.write(chunk)

This will save the file at MEDIA_ROOT/tmp/ as your default_storage will unless told otherwise.

8đź‘Ť

Here is another way to do it with python’s mkstemp:

### get the inmemory file
data = request.FILES.get('file') # get the file from the curl

### write the data to a temp file
tup = tempfile.mkstemp() # make a tmp file
f = os.fdopen(tup[0], 'w') # open the tmp file for writing
f.write(data.read()) # write the tmp file
f.close()

### return the path of the file
filepath = tup[1] # get the filepath
return filepath
👤David542

5đź‘Ť

Your best course of action is to write a custom Upload handler. See the docs . If you add a “file_complete” handler, you can access the file’s content regardless of having a memory file or a temp path file. You can also use the “receive_data_chunck” method and write your copy within it.

Regards

👤Arthur Debert

4đź‘Ť

This is how I tried to save the file locally

    file_object = request.FILES["document_file"]
    file_name = str(file_object)
    print(f'[INFO] File Name: {file_name}')
    with open(file_name, 'wb+') as f:
        for chunk in file_object.chunks():
            f.write(chunk)
👤Prasad

4đź‘Ť

Using default_storage (as mentioned in this answer) is not a good option (at least to me!). I would rather use FileSystemStorage directly.

from django.core.files.storage import FileSystemStorage
from django.http import HttpResponse


def simple_view(request):
    in_memory_file_obj = request.FILES["file"]
    FileSystemStorage(location="/tmp").save(in_memory_file_obj.name, in_memory_file_obj)
    return HttpResponse("Success")

Notes:

  • The location can be any value that suites for a directory path. It can even be a /tmp.

  • Solution tested with Django 4.1

👤JPG

Leave a comment